0

I was learning about lexical this in ES6, and I countered this example :

let person = {
    name : 'Alex',
  cars : ['Ferrari','Jaguar','Bugatti','Cadillac'],
  toString : function(){
    for(let car of cars){
            console.log(`${this.name} has ${car}`)
        }
  }
}

person.toString();

so let's say I want to convert the toString function to an array function so I'll have this :

let person = {
    name : 'Alex',
  cars : ['Ferrari','Jaguar','Bugatti','Cadillac'],
  toString : () => {
    for(let car of cars){
            console.log(`${this.name} has ${car}`)
        }
  }
}

person.toString();

in this example cars is undefined, why I'm getting that, and how can I call cars from the person object in that example.

the same goes for this :

let person = {
    name : 'Alex',
  cars : ['Ferrari','Jaguar','Bugatti','Cadillac'],
  toString : () => {
    cars.forEach(car => console.log(`${this.name} has ${car}`));
  }
}

person.toString();
Renaud is Not Bill Gates
  • 1,684
  • 34
  • 105
  • 191
  • 1
    step 1, don't use an arrow function, it's `this` is different. step 2, iterate `this.cars`, not `cars` – Jaromanda X Jul 04 '17 at 02:15
  • but, for your last example, don't use arrow for toString, but DO use arrow for forEach function ... so (shorthand) `toString() { this.cars.forEach(car => ...` – Jaromanda X Jul 04 '17 at 02:16
  • `cars` is an object property. It must be accessed with `obj.cars` syntax. You cannot access it as `cars`. It's not a local variable. In Javascript, there is no implicit attachment of `this` to a property like there is in some other languages. You will have to reference `person.cars`. – jfriend00 Jul 04 '17 at 05:57

2 Answers2

3

The first example is already broken.

in this example cars is undefined, why I'm getting that

There is no variable with name cars. Whether or not you are using an arrow function doesn't make a difference.

how can I call cars from the person object in that example.

Use a method or function expression and reference it with this.cars:

let person = {
  name : 'Alex',
  cars : ['Ferrari','Jaguar','Bugatti','Cadillac'],
  toString() {
    for(let car of this.cars){
            console.log(`${this.name} has ${car}`)
        }
  }
}

Arrow functions cannot be used as instance methods, because in instance methods you don't want lexical this. Learn more: Arrow function vs function declaration / expressions: Are they equivalent / exchangeable?

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
0

Because of your arrow function that your this apply to your object which the function you called.

correct

let person = {
  name : 'Alex',
  cars : ['Ferrari','Jaguar','Bugatti','Cadillac'],
  toString : function() {
   this.cars.forEach(car=>{
        console.log(`${this.name} has ${car}`)
    })
  }
}

person.toString();

The last arrow function in foreach is apply this of your object that why you didn't need to use clourse like this.cars.forEach(...)(this.name).

Rach Chen
  • 1,322
  • 2
  • 10
  • 26