El valor de la palabra clave `this` de una función devuelta por un getter

15

Encontré un valor inesperado de esta palabra clave en el siguiente ejemplo:

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


x.func1(x)

El valor de esta palabra clave es el objeto x como si se ejecutara desde ese objeto, espero que solo la función get que tiene esta palabra clave sea igual al objeto llamante x

este ejemplo nos muestra la diferencia

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

x.func2()(x);

En ambos ejemplos, func1, que es la función getter, y func2, que es un método del objeto, se ejecutan desde el objeto x , y luego se ejecuta la función devuelta. Entonces, ¿por qué este valor en el primer ejemplo no es igual al objeto global en lugar del objeto x ?

Kirollos Nasr
fuente
3
Realmente, una pregunta realmente interesante. Nunca antes había pensado en esta arruga.
TJ Crowder
1
" Como si se ejecuta desde ese objeto " - sino que se ejecuta en ese objeto, allí mismo: x.func1().
Bergi

Respuestas:

13

Esa es una pregunta muy interesante.

Esto se debe a que la función se llama inmediatamente en el resultado de un acceso a la propiedad. Entonces estos son 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);

En ambos casos:

  1. Se lee el valor de la propiedad, lo que da como resultado una referencia de función.
  2. Esa función se ejecuta como parte de la misma expresión de acceso a la propiedad.

El hecho de que func1sea ​​una propiedad de acceso y func2una propiedad de datos no importa. Lo importante es cómo se usa el valor resultante de leer la propiedad.

TJ Crowder
fuente
1
Pensé que toda la expresión se evaluará al objeto de función y luego se ejecutará. Gracias lo tengo
Kirollos Nasr
1
@KirollosNasr Sí, lo es, pero en la expresión x.func1mantiene la referencia xcomo contexto para la llamada posterior, en contraste con x.func2()(de su pregunta) que también se evalúa como una función pero no es una expresión de acceso de miembro.
Bergi
1
@ Bergi: ¿creo que te refieres x.func2()(x);?
TJ Crowder
1
@TJCrowder Sí, me refiero a las expresiones dentro x.func1(x)yx.func2()(x)
Bergi
1
@ Bergi, sí, tiene una parte difícil. Pero ahora está más claro Gracias a TJ Crowder y a ti
Kirollos Nasr