Ray Cheng
Ray Cheng

Reputation: 12576

JavaScript extension on Array

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

Answers (4)

ruakh
ruakh

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

Steve Wakeford
Steve Wakeford

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

Dave Walker
Dave Walker

Reputation: 3523

That is expected from the 'for the for(var in items)' as it enumerates through object fields, not indexes.

Upvotes: 0

Brad Christie
Brad Christie

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

Related Questions