Reputation: 12576
I'm writing an extension method for Array which accepts a function and then call it for each items in the Array.
It works fine except the extension itself is added into the Array after the function call. So at the alert part, the third alert shows my foo function in string.
Here's the code:
Array.prototype.foo = function (F) {
for (var i in this) {
this[i] = F(this[i]);
}
}
var items = ["a", "b"];
items.foo(function (data) {
return data + 1;
});
for (var i in items) {
alert(items[i]); // expected to see a1 and b1 but also displayed foo as string.
}
Upvotes: 1
Views: 82
Reputation: 183321
I +1'd Brad Christie's answer, but I wanted to add that it is possible, starting in JavaScript 1.8.5, to create a property that does not show up in for(var ... in ...)
statements, by using the defineProperty
method. That would look like this:
Object.defineProperty
(
Array.prototype,
'foo',
{
value:
function (f)
{
for (var i = 0; i < this.length; ++i)
this[i] = f(this[i]);
}
}
);
var items = [1, 2, 3];
items.foo(function (n) { return 2 * n; }); // now items = [2, 4, 6]
for (var i in items)
alert(items[i]); // alerts 2, then 4, then 6
That said, JavaScript 1.8.5 only came out in 2010, so it might not be a good idea, yet, to write code that depends on it.
Upvotes: 2
Reputation: 11
If you had intended to loop over the object fields you could add a typeof(this[i]) != 'function'
check before your assignment.
Upvotes: 0
Reputation: 3523
That is expected from the 'for the for(var in items)' as it enumerates through object fields, not indexes.
Upvotes: 0
Reputation: 101614
That's because for in
is going through the keys of the array, not the elements. You'll want to switch your loop (I believe):
for (var e = 0; e < this.length; e++){
// call against this[e] now
}
For example:
var ary = ['a','b','c']
for (var a = 0; a < ary.length; a++){
console.log(ary[a]); // echos a, b, c
}
var obj = {a:'X',b:'Y',c:'Z'}
for (var a in obj){
console.log(a); // echos a, b, c
console.log(obj[a]) // echos X, Y, Z
}
Upvotes: 4