Reputation: 245
I'm trying to define a class with two public methods. It so happens that one of the methods is useful for implementing the other one, but for the life of me, I cannot get that function to be recognized within the scope of the other one. I have no idea whether this is something specific to node.js or not, but in case it matters, this is running under node.
Here is a short toy problem which reproduces the behavior I'm seeing:
function Foo() {
this.list = [];
}
Foo.prototype = {
addSeveral: function(arr) { arr.forEach(function(v) { addOne(v)} ) },
addOne: function(item) { list.push(item); }
}
f = new Foo();
f.addSeveral([1,2,3]);
When I run this, it blows up with:
[jasonb@localhost]$ node testobj.js
/home/jasonb/work/testobj.js:6
Foo.prototype.addSeveral = function(arr) { arr.forEach(function(v) { addOne(v)}
^
ReferenceError: addOne is not defined
at /home/jasonb/work/entity_mapping/testobj.js:6:70
I've tried every variation I can find on how to assign stuff to a class's prototype, with the same results. And if I try to call this.addOne(v)
instead, it still blows up, but with TypeError: Object #<Object> has no method 'addOne'
How can I call addOne()
within addSeveral()
?
Upvotes: 3
Views: 3795
Reputation: 20315
You can pass this
to forEach
:
addSeveral: function (arr) {
arr.forEach(function (v) {
this.addOne(v)
}, this)
}
Or you can use bind:
addSeveral: function (arr) {
arr.forEach((function (v) {
this.addOne(v)
}).bind(this))
}
But what I would do is push.apply
:
addSeveral: function (arr) {
[].push.apply(this.list, arr)
}
Upvotes: 1
Reputation: 144872
Because forEach
invokes a callback function for each element of the array, you're losing context (this
is not the Foo
object inside your callback). You can close over a reference:
Foo.prototype = {
addSeveral: function(arr) { var self=this; arr.forEach(function(v) { self.addOne(v)} ) },
addOne: function(item) { this.list.push(item); }
}
...or just use a regular loop, which will have much better performance – function invocation is expensive.
addSeveral: function(arr) { for(var i = 0; i < arr.length; i++) this.addOne(arr[i]); };
Upvotes: 9