Reputation: 129
I'm trying implement a simple call to forEach
to run the logMe
function on all items in the automobiles array. The output is unexpected. All variables read "undefined."
function Automobile(year, make, model, type) {
this.year = year;
this.make = make;
this.model = model;
this.type = type;
}
Automobile.prototype.logMe = function(boolVal) {
if (boolVal == true) {
console.log(this.year + ' ' + this.make + ' ' + this.model + ' ' + this.type);
} else {
console.log(this.year + ' ' + this.make + ' ' + this.model);
}
}
var automobiles = [
new Automobile(2010, "Toyota", "Tacoma", "Pickup"),
new Automobile(2005, "Lotus", "Elise", "Roadster"),
new Automobile(2008, "Subaru", "Outback", "Wagon")
];
automobiles.forEach(Automobile.prototype.logMe.bind(true)); //the problem
automobiles[0].logMe(true); //test logMe function
The output:
undefined undefined undefined
undefined undefined undefined
undefined undefined undefined
1995 Honda Accord Sedan
Upvotes: 1
Views: 992
Reputation: 42352
Function.prototype.bind
creates a new function and you must pass in the value of this
- the construct which calls the function.
If you want to create an array of functions that can be called later like this, you should be using bind
like below, otherwise just call the function inside the forEach
.
var caller = [];
automobiles.forEach(function(element) {
caller.push(Automobile.prototype.logMe.bind(element));
}, caller);
caller[0](true);
Demo below:
function Automobile(year, make, model, type) {
this.year = year;
this.make = make;
this.model = model;
this.type = type;
}
Automobile.prototype.logMe = function(boolVal) {
if (boolVal == true) {
console.log(this.year + ' ' + this.make + ' ' + this.model + ' ' + this.type);
} else {
console.log(this.year + ' ' + this.make + ' ' + this.model);
}
}
var automobiles = [
new Automobile(2010, "Toyota", "Tacoma", "Pickup"),
new Automobile(2005, "Lotus", "Elise", "Roadster"),
new Automobile(2008, "Subaru", "Outback", "Wagon")
];
var caller = [];
automobiles.forEach(function(element) {
caller.push(Automobile.prototype.logMe.bind(element));
}, caller);
caller[0](true); //test logMe function
Upvotes: 1
Reputation: 77400
The first argument to Function.bind()
is the value for this
within the function. In your sample, this
is bound to true
, which is why you get undefined
for the property values.
forEach
will pass the element as the first argument to the callback. Thus, instead of passing a bound method, you can define a lambda that calls logMe
on its 1st argument.
automobiles.forEach(function(car, i, cars) {car.logMe(true);});
Upvotes: 2