index into javascript array with variable uses array scope variable - javascript

I've never seen this happen before, and can't find anything about this on the internet. I'm not even really sure how to ask this question.
I can't seem to reproduce this at will, but it is consistent once it starts happening.
When i try to access an element of an array with a variable, such as an iterator, the array is seeing the iterator variable as undefined, because it thinks i'm asking for a member of the array.
so for example:
for(var x = 0; x < width; ++x)
{
if(something != somethingelse)
{
var element = array[x]; // exception
}
}
this for example may cause an exception because x is undefined. So in firefoxes debugger, i check the value of the "x" inside [x], it is undefined. i check the value of "x" in the for loop line, it is a correct integer. So i put a watch on the x inside [x] and find that i'm watching "array.x".
I've been using javascript for years, but i haven't seen this happen before. I don't usually debug with firefox though, so is this an issue with firefox?
i guess my question is, is there anything obvious that i may be doing wrong by accessing an array using a variable?
I forgot to mention, i do have a fix, but it's not something i would like to always do when this happens. right before i access the element inside the array, i set the array member variable to the variable i'm using as an index.
for example:
for(var x = 0; x < width; ++x)
{
if(something != somethingelse)
{
array.x = x;
var element = array[x]; // exception
}
}

Related

Consequences of variable scope [duplicate]

This question already has answers here:
JavaScript variables declare outside or inside loop?
(12 answers)
Closed 5 years ago.
what's the difference between the following two sections of code?
one.
var arr = [70,80,150,310,260,100,78];
var pointArr=[];
var point={};
for (var i = 0; i < arr.length; i++) {
point.x=i*80;
point.y=(arr[i]/600)*240;
pointArr.push(point);
console.log(point);
console.log(pointArr);
}
two
var arr = [70,80,150,310,260,100,78];
var pointArr=[];
for (var i = 0; i < arr.length; i++) {
//diff
var point={};
point.x=i*80;
point.y=(arr[i]/600)*240;
pointArr.push(point);
console.log(point);
console.log(pointArr);
}
results:
one
enter image description here
two
enter image description here
For code one, point is initialised once. Whereas for code two, it is initialised for every loop.
when you initialize the variable inside the loop, it will initialize (reset) with each iteration. This means that you will push data to an empty object and log that object every time the for loop runs, instead of continuously pushing to the object that was created outside the loop in your first example. Does that make sense?
In JavaScript Objects are passed by reference. Whereas primitive types are passed by value and are immutable.
So in your first code example the variable point will be stored in memory as a reference in form of a pointer. Inside the loop you keep pushing the same reference to pointArr. Changing the x and y property of point will just change the referenced value. This has nothing to do with the loop itself.
Just change your first example to the following:
var arr = [70,80,150,310,260,100,78];
var pointArr=[];
var point={};
for (var i = 0; i < arr.length; i++) {
point.x=i*80;
point.y=(arr[i]/600)*240;
pointArr.push(point);
}
window.setTimeout(function() {
point.x = 'foo';
point.y = 'bar';
console.log(pointArr);
}, 2000)
By looking at the console output you can tell that you have several occurrences of the same reference inside pointArr.
By re-declaring point inside your loop, like you did in the second example, you simply created a new reference for each point.
You may want to take a look at the following link which explains this in more detail.
Primitive Types and Reference Types
Hope that helps.

Variable becomes NaN outside for loop in JavaScript

I'm curious how a variable can be an integer inside a for loop but become NaN immediately outside the loop.
var sumNum = 0;
for (var i = data.length - 1; i >=0; i--) {
sumNum += data[i].stored_value;
// check value inside loop
console.log(sumNum);
}
// check value outside loop
console.log(sumNum);
Result:
The first console.log(sumNum) prints increasing integers as we iterate and add up stored_value's in array. But the second console.log(sumNum) prints NaN.
I read a related thread (Variable becomes Nan when i try to use it outside of the .each function) explaining how this could happen if variable is instantiated inside the loop, but in my case the variable is created globally first.
Could anyone share some insight on how this can happen?
add a check of number in following code
if(isNaN(data[i].stored_value) == false) {
sumNum += data[i].stored_value;
}
Because if you add a non numeric value (may be some blank value) in some variable it becomes NaN

Why is `s.len` undefined (and not 4) while `s` has the value `test`? - JavaScript

I am puzzled with this one. I have the following code.
var s = "test";
s.len = 4;
var t = s.len;
The question is why the variable t has a value of undefined.
If you check the s.len after that code it is undefined.
If you check s the value is test. Not sure what is going on here. I am sure there is an explanation, but can't get my head around that and don't know how to search that.
For those who consider to vote down. This is a question we got in a course, and we are expected to prepare for the next session with this riddle.
I am not new to programming, but I fail to research how JavaScripts treats this code. It is valid code really, execute it in your Dev Tools and you will see.
I define a property for the string s called len assign to it the value 4. This property is, I believe created, but undefined. I would like to now why is it ? Is it specific to strings in JavaScript ?
but I fail to research how JavaScripts treats this code.
That is easy: strings are primitive types in JS, which means they don't have properties by themselves.
For . operator to work with them (e.g. for .length call) javascript defines such a thing called "wrapper objects".
So when you try to access a property of a primitive object - a temporary wrapper object is created that does behave as an object, hence you can access and assign properties to it.
The problem is that the wrapper object is temporary, so after it's used to access a property the object is discarded with all its state.
That's why when you assign a .len property you cannot access it on the next line: it's lost.
So a pseudo code for what actually happens behind the scenes for your code is
var s = "test";
(new String(s)).len = 4; // here you add an attribute for a new object
// and `s` is left untouched
var t = s.len;
The question is why the variable t has a value of undefined.
Because you have defined s as a string not as an object. so s.len should be undefined!
I am not sure what are you trying to do. But if you want to get the length of s then t = s.length will simply work.
I define a property for the string s called len assign to it the value 4. This property is, I believe created, but undefined. I would like to now why is it ? Is it specific to strings in JavaScript ?
You can find the answer from this question
run :
var s1 = "test";
console.log(typeof s1)//string
var s2 = {}
console.log(typeof s2)//object
s1.len = 4;
s2.len = 4;
console.log(s1.len);//undefine
console.log(s2.len);//4

difference between for..in and for loops, and counter declaration

the difference (speed, performace, side effects, ...) between implementations of the for loop:
between
var i;
for(i = 0; i < length; i++){ //Do something}
// more code
and
for(var i = 0; i < length; i++){ //Do something}
// more code
and
for(i = 0; i < length; i++){ //Do something}
// more code
and between
var e;
for( e in array){ //Do something}
// more code
and
for(var e in array){ //Do something}
// more code
and
for(e in array){ //Do something}
// more code
There is no difference.
JavaScript variables have only function scope, and although you can place a var statement in the initialisation part of a for loop in reality the declaration is "hoisted" to the top of the scope such that when your second case examples run they're treated exactly like the first cases.
EDIT: Since you updated the question after I answered, the third syntax that you added where you don't use the var keyword means the variable i (or e) will be created as a global - unless it already exists as a global in which case the existing variable will be overwritten. Global variable access is slower than local variable access.
NOTE: my interpretation of the question is that it is not comparing a standard for loop with the for..in variant, it is just compared the different variable declaration methods with each other for a standard for loop, then doing the same again for a for..in loop.
There is no difference in relation to the declariation of your counter variable..
BUT ALWAYS DECLARE YOUR VARIABLES WITH var
Otherwise they pollute javascript's already dirty global scope...
As far as for...in vs traditional for look here...
(Which is my answer to the duplicate question...)
Yes, there is a difference between for loop and for/in loop in javascript. Here is what is different
consider this array
var myArr = ["a", "b", "c"];
Later, I add an element to this array, but in a different way, like so:
myArr[myArr.length + 1] = "d";
At this point of time, this is what the array looks like, if you console.log it
["c", "b", "a", undefined × 1, "d"]
Now, let us loop through the array using for and for/in loop and see what the difference is:
first, lets try the for loop
for(var i = 0; i != myArr.length; i++) { // note, i used " != " instead of " < ". Yes this is faster.
console.log(myArr[i]);
}
// output will look like this:
// "a"
// "b"
// "c"
// undefined × 1
// "d"
// - This still shows the undefined value in the array.
Now, lets look at the for/in loop
for(key in myArr) {
console.log(myArr[key]);
}
// array will look like:
// "a"
// "b"
// "c"
// "d"
// This will skip the undefined value.
Difference 1: The javascript interpreter will skip all values that are null or undefined when using the for/in loop. Also, the for/in loop will convert all values if it encounters a primitive value, to its equivalent wrapper object. Where as the for loop doesn't do this.
Difference 2: When using the for loop, we declared the variable i within the loop, this variable will be scoped within a function, if the for loop is written within that function. Which means, until the function ends, the variable i is still available, even outside of the for loop, but within that function. Where as, in case of the for/in loop, the scope of the "key" variable dies immediately after the for/in loop stops executing, which means, there is less memory utilization.

Javascript: Mozilla .watch() functionality for all properties of an object (possibly cross-browser)

https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Object/watch
The .watch() method does this in short: "Watches for a property to be assigned a value and runs a function when that occurs."
Long descriptive form: "Watches for assignment to a property named prop in this object, calling handler(prop, oldval, newval) whenever prop is set and storing the return value in that property. A watchpoint can filter (or nullify) the value assignment, by returning a modified newval (or by returning oldval)."
There is a question for getting it to work in all browsers here: Object.watch() for all browsers?
I am looking for something similar to that. What I'm looking for is a method I can use to fit this specification: "Watches for assignment to any property in this object and runs a function when that occurs." The main difference is that it is any property, and just any specific property.
Can somebody create such a method or if they know such a method is already in existence, link to it? It'd be useful to have it work in all browsers (minus IE, or minus IE8 if IE9 conforms)
Edit: For an example of what I mean, I'll show what I need it for.
var DiscreteLine = function (leftBound, length){
this.positive = [];
this.negative = [];
this.length = length;
this.leftBound = leftBound;
this.rightBound = leftBound + length
if (this.leftBound < 0){
this.negative.length = (leftBound * -1) + 1;
} else {
this.negative.length = 0;
}
if (this.rightBound >= 0){
this.positive.length = rightBound + 1;
} else {
this.positive.length = 0;
}
this.watchObject = new ObjectWatcher(handler(prop, oldval, newval){ /* some stuff */ });
}
Then, when for example, if somebody did the following:
theLine = new DiscreteLine(-2, 4);
theLine[-8] = 10;
The handler would call, with the arguments ("-8", undefined, 10). (What would end up happening is, is that the script would recalculate leftBound and length properties automatically (like how Arrays automatically update the length property).
This would basically require overriding the setter for a property of an already defined object. As far as I know, this is only possible in ECMAScript 5 (via Object.defineProperty) and at the moment, I'm not sure which browsers support this, if at all, so it wouldn't be "cross-browser" as you had asked.
Edit: Your example makes your requirement clear now. I'm afraid the language doesn't provide any way to be notified when new properties are added to an object. In your example, you really don't have any choice except to replace the array notation with a function call.

Categories

Resources