I'm testing classes in ES6 using traceur but it's not working as I expected.
I am trying to use a method as a reference in another class but when it's called I get the reference of the caller class when read the value of this
.
Here is my code:
class A {
constructor(anotherMethod){
this.anotherMethod = anotherMethod;
this.name = "A";
}
myMethod (){
console.log(this.name);
this.anotherMethod();
}
}
class B {
constructor(){
this.a = new A(this.myMethod);
this.name = "B";
}
myMethod(){
console.log(this.name);
}
}
var c = new B();
c.a.myMethod();
My expected log is:
A
B
But it is showing:
A
A
In class B, when the constructor function runs:
this.a = new A(this.myMethod);
You're actually setting the method myMethod
of B to A. When A's constructor runs,
this.myMethod, is set to A's anotherMethod. Now if you try printing this.a
in your B's constructor you will get name : A
. Which is actually referencing the class A.
Now when you try executing the method, c.a.myMethod()
, As A contains the reference to class A
, it's invoking the myMethod
of A. Inside this method, this
will refer to the current execution context object which is A. That's the reason why you're seeing A
in both the consoles.
In short, You're only assigning the function to A and not setting the context.
You can force fat arrow
using below:
class B {
constructor(){
this.a = new A(this.myMethod);
this.name = "B";
}
myMethod = () => {
console.log(this);
}
}
Now you will get the desired output. But unfortunately traceur
doesn't support it. Only babel supports fat arrow
inside functions which is part of ES7 stage 0 Class Properties
.
As suggested by Felix King: Binding the context using bind
is more than enough currently
class B {
constructor(){
this.a = new A(this.myMethod.bind(this));
this.name = "B";
}
myMethod() {
console.log(this);
}
}