1

This works:

class C {
    constructor(p1, p2) {
        this.p1 = 0;
        this.p2 = [];
        this.setP1(p1);
        p2.forEach(p => this.addP2(p));
    }
    setP1(p) { this.p1 = p }
    addP2(p) { this.p2.push(p) }
}

let c = new C(10,[20]);
console.log(c);
C { p1: 10, p2: [ 20 ] }

But this doesn't:

class C {
    constructor(p1, p2) {
        this.p1 = 0;
        this.p2 = [];
        this.setP1(p1);
        p2.forEach(this.addP2); // <- changed here
    }
    setP1(p) { this.p1 = p }
    addP2(p) { this.p2.push(p) }
}

let c = new C(10,[20]);
console.log(c);
addP2(p) { this.p2.push(p) }
                ^ TypeError: Cannot read property 'p2' of undefined

And there are two things I don't understand:

  • Why does it work? In both cases, setP1 is not explicitly bound to this, so how come it successfully updates the p1 property in the first case? Shouldn't it execute in a context where this is undefined and throw a Cannot read property 'p1' of undefined?

  • Why doesn't it work? p2.forEach(p => this.addP2(p)); is apparently equivalent to p2.forEach(this.addP2); because addP2 takes only one argument. What is happening that makes the first work, but the second crash?

Nino Filiu
  • 16,660
  • 11
  • 54
  • 84
  • For second case, think of it like `callback = this.addP2; callback(item, index, arr);`. Then there's no calling context. Use arrow function like in first case, or `.bind`, or pass another argument to `forEach` to provide a `this` – CertainPerformance Jan 09 '19 at 01:57
  • `p2.forEach(p => this.addP2(p));` is equivalent to `p2.forEach(this.addP2.bind(this));` – visibleman Jan 09 '19 at 02:01

0 Answers0