Behaviour of Javascript array objects
function map(f, a) {
for(var i in a) {
a[i] = f(a[i]);
}
}
var a = [0, 1, 2, 3];
map(function(x) { return x = x * x }, a);
console.log(a);
a: [0, 1, 4, 9]
开发者_JS百科
However, If I change map(f, a)
to:
function map(f, a) {
for(var i in a) {
f(a[i]);
}
}
var a = [0, 1, 2, 3];
map(function(x) { return x = x * x }, a);
console.log(a);
a remains unchanged as: [0, 1, 2, 3]
I'm not sure what's happening here. It appears as if the interpreter considers a[i]
as a reference to a property of the object a
in map(f, a)
but once passed into f
it turns into a typeof number
.
Don't use for(... in...)
on Arrays. Use a for loop
.
Enumeration order with for in
is NOT guaranteed. It will also iterate over properties (not the built ins but stuff that were set by JS code) and stuff on the prototype, and then all hell breaks loose.
Next thing, all values except for arrays and objects are pass by value (basically arrays and objects are also pass by value, but the value is a pointer to the object).
So you're not modifying the value inside the array in this case, but the local variable x
which just happens to have them same value.
return x = x * x
the assignment is superfluous.
Fixed version
function map(f, a) {
for(var i = 0, l = a.length; i < l; i++) {
a[i] = f(a[i]);
}
}
var a = [0, 1, 2, 3];
map(function(x) { return x * x }, a);
console.log(a);
This is correct behavior, it's the value of a[i]
is passed into f([i])
, not the reference to it, so that x
inside is a distinctly different variable/reference.
In the first version you're taking the result of that still different x
(returned by the function) and assigning it to that array position afterwards...that's the only way to use that new value for something.
This call:
a[i] = f(a[i]);
is actually similar to this:
var arg = a[i];
var res = f(arg);
a[i] = res;
This is called "call-by-value", see here:
- http://en.wikipedia.org/wiki/Call_by_value
Arrays in JavaScript are Objects, and Objects are always reference types.
Up to the point where a
exists inside the map function you have been passing it as an entire array which means that changes you make to a
will be visible externally.
Once you de-reference the array with a[i]
you have a variable of type Number
which is not a reference type. Therefore, changes to x
in your anonymous function will not be propagated back to the array, and are only visible inside the anonymous function itself.
精彩评论