Esta palabra clave

La palabra clave this hace referencia al valor del objeto que está vinculado al en el momento de la llamada, lo que significa que su valor es diferente según de si una función se llama como método, como función independiente o como constructor.

Cuando se llama a una función, se crea una instancia de la palabra clave this detrás escenas como una referencia al objeto que contiene esa función, lo que le da acceso a las propiedades y los métodos definidos junto con él desde su alcance. En algunos casos, trabajar con this es similar a trabajar con una variable declarada con const. Al igual que una constante, this no se puede quitar y su valor no se puede pero los métodos y las propiedades del objeto al que la palabra clave this que contiene pueden modificarse.

Vinculación global

Fuera de una función o del contexto de un objeto, this se refiere al propiedad globalThis, que es una referencia al objeto global en la mayoría entornos de JavaScript. En el contexto de una secuencia de comandos que se ejecuta en un navegador web, El objeto global es el objeto window:

this;
> Window {0: Window, window: Window, self: Window, document: document, name: '', location: Location, ...}

En Node.js, globalThis es el objeto global:

$ node
Welcome to Node.js v20.10.0.
Type ".help" for more information.
> this
<ref *1> Object [global] {
...
}

Fuera del modo estricto, this también hace referencia al objeto global dentro de un función, porque el elemento superior Window es el objeto que efectivamente "es propietario" esas funciones.

function myFunction() {
    console.log( this );
}
myFunction();
> Window {...}

(function() {
    console.log( this );
}());
> Window {...}

Cuando se usa el modo estricto, this tiene un valor de undefined dentro de un función:

(function() {
    "use strict";
    console.log( this );
}());
> undefined

Antes de la introducción del modo estricto, se agregó un valor null o undefined para this. se reemplazaría por una referencia al objeto global. Es posible que a veces veas vinculación global conocida como “vinculación predeterminada” debido a este comportamiento heredado.

Vinculación implícita

Cuando se llama a una función como método de un objeto, se crea una instancia de this dentro ese método se refiere al objeto que contiene el método, lo que da acceso al y las propiedades asociadas:

let myObject = {
    myValue: "This is my string.",
    myMethod() {
            console.log( this.myValue );
    }
};

myObject.myMethod();
> "This is my string."

Puede parecer que el valor de this depende de cómo una función y su del objeto que los contiene. En cambio, el contexto para el valor de this es el contexto de ejecución actual. En este caso, el contexto de ejecución es que el El objeto myObject llama al método myMethod, por lo que myObject es el valor. para this. Esto puede parecer un tecnicismo en el contexto de la ejemplos, pero para usos más avanzados de this, es una distinción esencial tener en cuenta.

En general, usa this de maneras que no esperen que el código que lo rodea tenga una estructura en particular. La excepción a esta regla es ES5. Funciones de flecha.

this en funciones de flecha

En las funciones de flecha, this se resuelve en una vinculación en un entorno de cierre léxico. Esto significa que this en una función de flecha hace referencia al valor de this en la función de esa función el contexto de cierre más cercano:

let myObject = {
    myMethod() { console.log( this ); },
    myArrowFunction: () => console.log( this ),
    myEnclosingMethod: function () {
        this.myArrowFunction = () => { console.log(this) };
    }
};

myObject.myMethod();
> Object { myMethod: myMethod(), myArrowFunction: myArrowFunction() }

myObject.myArrowFunction();
> Window {...}

En el ejemplo anterior, myObject.myMethod() registra myObject como el objeto. al que le pertenece ese método, pero myObject.myArrowFunction() muestra globalThis (o undefined), ya que la instancia de this dentro de la función de flecha se refiere, en cambio, al alcance envolvente más alto.

En el siguiente ejemplo, myEnclosingMethod crea una función de flecha en el que lo contiene cuando se ejecuta. La instancia de this dentro del flecha ahora hace referencia al valor de this dentro del entorno, que es el método que contiene esa función flecha. Debido a que el el valor de this dentro de myEnclosingMethod se refiere a myObject, después de que define la función flecha, this dentro de la función flecha también hace referencia a myObject:

let myObject = {
    myMethod() { console.log( this ); },
    myEnclosingMethod: function () {
        this.myArrowFunction = () => { console.log(this) };
    }
};

myObject.myEnclosingMethod();
myObject.myArrowFunction();
> Object { myMethod: myMethod(), myArrowFunction: myArrowFunction() }

Vinculación explícita

La vinculación implícita controla la mayoría de los casos de uso para trabajar con this. Sin embargo, a veces puede necesitar el valor de this para representar una ejecución específica contextual, en lugar del contexto supuesto. Es ilustrativo, aunque un poco desactualizado, El ejemplo es trabajar con this en la función de devolución de llamada de un setTimeout. ya que esta devolución de llamada tiene un contexto de ejecución único:

var myObject = {
  myString: "This is my string.",
  myMethod() {
    console.log( this.myString );
  }
};
myObject.myMethod();
> "This is my string."

setTimeout( myObject.myMethod, 100 );
> undefined

Si bien desde entonces, esta deficiencia específica de setTimeout ya fue abordada por otras funciones, problemas similares de "pérdida" this ya se solucionaron creando una referencia explícita al valor de this dentro del alcance de la el contexto previsto. En ocasiones, es posible que veas instancias de this asignadas. a una variable con identificadores como that, self o _this en versiones heredadas de código abierto. Estas son convenciones de identificador comunes para variables que contienen un pasado el valor this.

Cuando llamas a una función con los métodos call(), bind() o apply(), this hace referencia de forma explícita al objeto al que se llama:

let myFunction = function() {
    console.log( this.myValue );
}

let myObject = {
   "myValue" : "This is my string."
 };

myFunction.call( myObject );
> "This is my string."
var myObject = {
  myString: "This is my string.",
  myMethod() {
    console.log( this.myString );
  }
};

setTimeout( myObject.myMethod.bind( myObject ), 100 );
> "This is my string."

La vinculación explícita anula el valor this proporcionado por la vinculación implícita.

let myObject = {
    "myValue" : "This string sits alongside myMethod.",
    myMethod() {
        console.log( this.myValue );
    }
};
let myOtherObject = {
    "myValue" : "This is a string in another object entirely.",
};

myObject.myMethod.call( myOtherObject );
> "This is a string in another object entirely."

Si se llama a una función de una manera que establezca el valor de this en undefined o null; ese valor se reemplaza por globalThis fuera de estricto modo:

let myFunction = function() {
    console.log( this );
}

myFunction.call( null );
> Window {...}

Del mismo modo, si se llama a una función de una manera que daría a this un valor , ese valor se sustituye por el objeto wrapper del valor primitivo Fuera del modo estricto:

let myFunction = function() {
    console.log( this );
}

let myNumber = 10;

myFunction.call( myNumber );
> Number { 10 }

En el modo estricto, un valor this pasado no se coerciona a un objeto de ninguna manera. incluso si es un valor primitivo, null o undefined:

"use strict";
let myFunction = function() {
    console.log( this );
}

let myNumber = 10;

myFunction.call( myNumber );
> 10

myFunction.call( null );
> null

Vinculación de new

Cuando se usa una clase como constructor con el La palabra clave new, this hace referencia a la instancia recién creada:

class MyClass {
    myString;
    constructor() {
        this.myString = "My string.";
    }
    logThis() {
        console.log( this );
    }
}
const thisClass = new MyClass();

thisClass.logThis();
> Object { myString: "My string." }

De manera similar, el valor de this dentro de una función de constructor a la que se llama con new se refiere al objeto que se crea:

function MyFunction() {
  this.myString = "My string.";
  this.logThis = function() {
    console.log( this );
  }
}
const myObject = new MyFunction();

myObject.logThis();
> Object { myString: "My string.", logThis: logThis() }

Vinculación del controlador de eventos

En el contexto de los controladores de eventos, el valor de this hace referencia al objeto que lo invoca. Dentro de la función de devolución de llamada de un controlador de eventos, significa this. hace referencia al elemento asociado con el controlador:

let button = document.querySelector( "button" );

button.addEventListener( "click", function( event ) { console.log( this ); } );

Cuando un usuario interactúa con button en el fragmento anterior, el resultado el objeto del elemento que contiene el mismo <button>:

> Button {}

Cuando se usa una función de flecha como devolución de llamada de objeto de escucha de eventos, el valor del De nuevo, el contexto de ejecución envolvente más cercano proporciona this. En la parte superior esto significa que this dentro de una función de devolución de llamada del controlador de eventos es globalThis (o undefined, en modo estricto):

let button = document.querySelector( "button" );

button.addEventListener( "click", ( event ) => { console.log( this ); } );
> undefined

Al igual que con cualquier otro objeto, cuando usas call(), bind() o apply() métodos para hacer referencia a la función de devolución de llamada de un objeto de escucha de eventos, this hace referencia al objeto de manera explícita:

let button = document.querySelector( "button" );
let myObject = {
    "myValue" : true
};
function handleClick() {
    console.log( this );
}

button.addEventListener( "click", handleClick.bind( myObject ) );
> Object { myValue: true }

Verifica tus conocimientos

¿Cuál es el objeto global de una secuencia de comandos que se ejecuta en un navegador web? a la que hace referencia this cuando se usa fuera de una función o el contexto de un objeto?

El objeto window
El objeto browser
El objeto undefined