14

I found an unexpected value of this keyword in the following example :

let x = {
    z : 10 ,
    get func1() {
        return function(v) {
            console.log(this === v);
        }
    }
}


x.func1(x)

The value of this keyword is the object x as if it's executed from that object, I expect only the get function that has this keyword equals to the calling object x

this example shows us the difference

let x = {
    func2() {
        return function(v) {
            console.log(this === v);
        }
    }
}

x.func2()(x);

In both examples func1 which is the getter function, and func2 which is a method of the object, are executed from the object x, and the returned function is then executed. So why this value in the first example not equals to the global object instead of the object x.

Kirollos Nasr
  • 315
  • 1
  • 7

1 Answers1

12

That's a very interesting question.

It's because the function is being called immediately on the result of a property access. So these are fundamentally equivalent:

let x = {
    get func1() {
        return function(v) {
            console.log(this === v);
        };
    },
    func2(v) {
        console.log(this === v);
    }
};

x.func1(x);
x.func2(x);

In both cases:

  1. The value of the property is read, resulting in a function reference.
  2. That function is executed as part of the same property access expression.

The fact that func1 is an accessor property and func2 is a data property doesn't matter. It's how the value resulting from reading the property is used that matters.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    I thought that the the whole expression will be evaluated to the function object and then executed. Thanks got it – Kirollos Nasr Jan 19 '20 at 12:53
  • 1
    @KirollosNasr Yes, it is, but in the expression `x.func1` it keeps the reference to `x` as the context for the subsequent call, in contrast to `x.func2()` (from your question) which evaluates to a function as well but is not a member access expression. – Bergi Jan 19 '20 at 23:47
  • 1
    @Bergi - I think you meant `x.func2()(x);`? – T.J. Crowder Jan 20 '20 at 07:13
  • 1
    @T.J.Crowder Yes, I refer to the expressions inside `x.func1(x)` and `x.func2()(x)` – Bergi Jan 20 '20 at 09:53
  • 1
    @Bergi yeah it has a tricky part. But now it's more clear Thanks to T.J. Crowder and you – Kirollos Nasr Jan 20 '20 at 11:44