Значение ключевого слова `this` функции, возвращаемой получателем

15

Я обнаружил неожиданное значение этого ключевого слова в следующем примере:

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


x.func1(x)

Значением этого ключевого слова является объект x, как если бы он выполнялся из этого объекта, я ожидаю, что только функция get с этим ключевым словом равна вызывающему объекту x

этот пример показывает нам разницу

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

x.func2()(x);

В обоих примерах func1, который является функцией getter, и func2, который является методом объекта, выполняются из объекта x , а затем выполняется возвращенная функция. Так почему же это значение в первом примере не равно глобальному объекту вместо объекта x .

Кироллос Наср
источник
3
Действительно, действительно интересный вопрос. Я никогда не думал об этой морщинке раньше.
TJ Crowder
1
« Как если он выполняется из этого объекта » , - но это будет выполняться на этом объекте, прямо там: x.func1().
Берги

Ответы:

13

Это очень интересный вопрос.

Это потому, что функция вызывается сразу после получения доступа к свойству. Так что это в основном эквивалентно:

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

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

В обоих случаях:

  1. Значение свойства читается, что приводит к ссылке на функцию.
  2. Эта функция выполняется как часть того же выражения доступа к свойству.

Факт, что func1это свойство доступа и func2является свойством данных, не имеет значения. Важно то, как используется значение, полученное в результате чтения свойства.

TJ Crowder
источник
1
Я думал, что все выражение будет оценено для объекта функции и затем выполнено. Спасибо, понял
Kirollos Nasr
1
@KirollosNasr Да, это так, но в выражении x.func1он сохраняет ссылку в xкачестве контекста для последующего вызова, в отличие от x.func2()(из вашего вопроса), который также оценивает функцию, но не является выражением доступа к члену.
Берги
1
@ Берги - я думаю, ты имел в виду x.func2()(x);?
TJ Crowder
1
@TJCrowder Да, я имею в виду выражения внутри x.func1(x)иx.func2()(x)
Берги
1
@ Берги, да, у него есть хитрая часть. Но теперь это стало понятнее. Спасибо Ти Джей
Краудеру