1

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

1

2 Answers 2

2

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);});
Sign up to request clarification or add additional context in comments.

3 Comments

Can you clarify what these three variables are?
Can you clarify what these three variables are? (car, i, cars) car = the object at the index, i = the index, what is cars ?
@user3612719 it's the "automobiles" array. The third parameter passed to a .forEach callback is the array being iterated.
1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.