O valor da palavra-chave `this` de uma função retornada de um getter

15

Encontrei um valor inesperado dessa palavra - chave no exemplo a seguir:

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


x.func1(x)

O valor dessa palavra-chave é o objeto x como se fosse executado a partir desse objeto. Espero que apenas a função get que tenha essa palavra - chave seja igual ao objeto que chama x

este exemplo mostra a diferença

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

x.func2()(x);

Nos dois exemplos, func1, que é a função getter, e func2, que é um método do objeto, são executados a partir do objeto x , e a função retornada é executada. Então, por que esse valor no primeiro exemplo não é igual ao objeto global em vez do objeto x .

Kirollos Nasr
fonte
3
Pergunta realmente interessante. Eu nunca tinha pensado nessas rugas antes.
TJ Crowder
11
" Como se ele é executado a partir desse objeto " - mas é executado no objeto, ali mesmo: x.func1().
Bergi 19/01

Respostas:

13

Essa é uma pergunta muito interessante.

É porque a função está sendo chamada imediatamente no resultado de um acesso à propriedade. Portanto, estes são fundamentalmente equivalentes:

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

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

Em ambos os casos:

  1. O valor da propriedade é lido, resultando em uma referência de função.
  2. Essa função é executada como parte da mesma expressão de acesso à propriedade.

O fato de func1ser uma propriedade de acessador e de func2propriedade de dados não importa. É como é importante o valor resultante da leitura da propriedade.

TJ Crowder
fonte
11
Eu pensei que toda a expressão será avaliada para o objeto de função e depois executada. Obrigado entendeu
Kirollos Nasr
11
@KirollosNasr Sim, é, mas na expressão x.func1mantém a referência xcomo o contexto da chamada subsequente, em contraste com x.func2()(da sua pergunta) que avalia também uma função, mas não é uma expressão de acesso de membro.
Bergi 19/01
11
@ Bergi - Eu acho que você quis dizer x.func2()(x);?
TJ Crowder
11
@TJCrowder Sim, refiro-me às expressões internas x.func1(x)ex.func2()(x)
Bergi 20/01
11
@ Bergi sim, tem uma parte complicada. Mas agora está mais claro Graças a TJ Crowder e você
Kirollos Nasr