javascript - method - ¿Cómo funciona la palabra clave "this"?
let in javascript w3schools (20)
Me he dado cuenta de que no parece haber una explicación clara de qué es this
palabra clave y cómo se utiliza correctamente (e incorrectamente) en JavaScript en el sitio de desbordamiento de pila.
He sido testigo de algún comportamiento muy extraño con él y no he entendido por qué ha ocurrido.
¿Cómo funciona this
y cuándo debe usarse?
Javascript es this
Invocación de función simple
Considera la siguiente función:
function foo() {
console.log("bar");
console.log(this);
}
foo(); // calling the function
Tenga en cuenta que estamos ejecutando esto en el modo normal, es decir, el modo estricto no se utiliza.
Cuando se ejecuta en un navegador, el valor de this
se registra como window
. Esto se debe a que la window
es la variable global en el alcance de un navegador web.
Si ejecuta este mismo fragmento de código en un entorno como node.js, this
se referirá a la variable global en su aplicación.
Ahora si ejecutamos esto en modo estricto agregando la instrucción "use strict";
al comienzo de la declaración de función, this
ya no se referiría a la variable global en ninguno de los entornos. Esto se hace para evitar confusiones en el modo estricto. this
, en este caso, simplemente se registra undefined
, porque eso es lo que es, no está definido.
En los siguientes casos, veríamos cómo manipular el valor de this
.
Llamando una función sobre un objeto
Hay maneras diferentes de hacer esto. Si ha llamado a métodos nativos en Javascript como forEach
y slice
, ya debería saber que this
variable en ese caso se refiere al Object
en el que llamó a esa función (Tenga en cuenta que en javascript, casi todo es un Object
, incluyendo Array
s y Function
s). Tome el siguiente código, por ejemplo.
var myObj = {key: "Obj"};
myObj.logThis = function () {
// I am a method
console.log(this);
}
myObj.logThis(); // myObj is logged
Si un Object
contiene una propiedad que contiene una Function
, la propiedad se llama un método. Este método, cuando se invoca, siempre tendrá this
variable establecida en el Object
que está asociado. Esto es cierto para los modos estrictos y no estrictos.
Tenga en cuenta que si un método se almacena (o, más bien, se copia) en otra variable, la referencia a this
ya no se conserva en la nueva variable. Por ejemplo:
// continuing with the previous code snippet
var myVar = myObj.thisMethod;
myVar();
// logs either of window/global/undefined based on mode of operation
Teniendo en cuenta un escenario más comúnmente práctico:
var el = document.getElementById(''idOfEl'');
el.addEventListener(''click'', function() { console.log(this) });
// the function called by addEventListener contains this as the reference to the element
// so clicking on our element would log that element itself
La new
palabra clave
Considere una función constructora en Javascript:
function Person (name) {
this.name = name;
this.sayHello = function () {
console.log ("Hello", this);
}
}
var awal = new Person("Awal");
awal.sayHello();
// In `awal.sayHello`, `this` contains the reference to the variable `awal`
¿Como funciona esto? Bueno, veamos qué sucede cuando usamos la new
palabra clave.
- Si se llama a la función con la
new
palabra clave, se inicializa inmediatamente unObject
de tipoPerson
. - El constructor de este
Object
tiene su constructor establecido enPerson
. Además, tenga en cuenta quetypeof awal
solo devolveríaObject
. - A este nuevo
Object
se le asignaría el prototipo dePerson.prototype
. Esto significa que cualquier método o propiedad en el prototipo dePerson
estaría disponible para todas las instancias dePerson
, incluyendoawal
. - La función
Person
sí se invoca ahora; siendothis
una referencia al objeto recién construidoawal
.
Bastante franco, ¿eh?
Tenga en cuenta que la especificación oficial de ECMAScript donde se indica que dichos tipos de funciones son funciones reales del constructor
. Solo son funciones normales, y las new
pueden usarse en cualquier función. Es solo que los usamos como tales, y por eso los llamamos solo como tales.
Llamando funciones en Funciones: call
y apply
Así que sí, dado que las function
s también son Objects
(y, de hecho, variables de primera clase en Javascript), incluso las funciones tienen métodos que son ... bueno, funciones seleccionadas.
Todas las funciones heredan de la Function
global, y dos de sus muchos métodos son de call
y apply
, y ambos pueden usarse para manipular el valor de this
en la función en la que se llaman.
function foo () { console.log (this, arguments); }
var thisArg = {myObj: "is cool"};
foo.call(thisArg, 1, 2, 3);
Este es un ejemplo típico de uso de call
. Básicamente toma el primer parámetro y lo establece en la función foo
como una referencia a thisArg
. Todos los demás parámetros pasados a la call
se pasan a la función foo
como argumentos.
Así que el código anterior registrará {myObj: "is cool"}, [1, 2, 3]
en la consola. Muy buena manera de cambiar el valor de this
en cualquier función.
apply
es casi lo mismo que aceptar call
ya que solo toma dos parámetros: thisArg
y una matriz que contiene los argumentos que se pasarán a la función. Por lo tanto, la call
anterior se puede traducir para apply
esta manera:
foo.apply(thisArg, [1,2,3])
Tenga en cuenta que la call
y la apply
pueden anular el valor de this
invocación del método de establecer por punto que analizamos en la segunda viñeta. Suficientemente simple :)
Presentando .... se bind
!
bind
es un hermano de call
y se apply
. También es un método heredado por todas las funciones del constructor de Function
global en Javascript. La diferencia entre bind
y call
/ apply
es que tanto la call
como la apply
invocarán la función. bind
, por otro lado, devuelve una nueva función con el thisArg
y los arguments
. Tomemos un ejemplo para entender mejor esto:
function foo (a, b) {
console.log (this, arguments);
}
var thisArg = {myObj: "even more cool now"};
var bound = foo.bind(thisArg, 1, 2);
console.log (typeof bound); // logs `function`
console.log (bound);
/* logs `function () { native code }` */
bound(); // calling the function returned by `.bind`
// logs `{myObj: "even more cool now"}, [1, 2]`
¿Ves la diferencia entre los tres? Es sutil, pero se utilizan de manera diferente. Al igual que call
y apply
, bind
también anulará el valor de this
conjunto mediante la invocación del método de puntos.
También tenga en cuenta que ninguna de estas tres funciones modifica la función original. call
y apply
devolverían el valor de las funciones recién creadas, mientras que bind
devolverá la función recién creada, lista para ser llamada.
Cosas extra, copia esto
A veces, no le gusta el hecho de que this
cambie con el alcance, especialmente el ámbito anidado. Echa un vistazo al siguiente ejemplo.
var myObj = {
hello: function () {
return "world"
},
myMethod: function () {
// copy this, variable names are case-sensitive
var that = this;
// callbacks ftw /o/
foo.bar("args", function () {
// I want to call `hello` here
this.hello(); // error
// but `this` references to `foo` damn!
// oh wait we have a backup /o/
that.hello(); // "world"
});
}
};
En el código anterior, vemos que el valor de this
cambió con el alcance anidado, pero queríamos el valor de this
del alcance original. Así que ''copiamos'' this
a that
y usamos la copia en lugar de this
. Listo, ¿eh?
Índice:
- ¿Qué se mantiene en
this
por defecto? - ¿Qué pasa si llamamos a la función como un método con notación de punto de objeto?
- ¿Qué pasa si usamos la
new
palabra clave? - ¿Cómo manipulamos
this
concall
yapply
? - Utilizando
bind
. - Copiando
this
para resolver problemas de alcance anidado.
Resumen de this
Javascript:
- El valor de
this
se determina por cómo no se invoca la función, ¡dónde se creó! - Por lo general, el valor de
this
está determinado por el Objeto que queda a la izquierda del punto. (window
en el espacio global) - En los detectores de eventos, el valor de se
this
refiere al elemento DOM en el que se llamó al evento. - Cuando se llama a la función con la
new
palabra clave, el valor de sethis
refiere al objeto recién creado - Se puede manipular el valor de
this
las funciones:call
,apply
,bind
Ejemplo:
let object = {
prop1: function () {console.log(this);}
}
object.prop1(); // object is left of the dot, thus this is object
const myFunction = object.prop1 // We store the function in the variable myFunction
myFunction(); // Here we are in the global space
// myFunction is a property on the global object
// Therefore it logs the window object
Ejemplos de oyentes de eventos:
document.querySelector(''.foo'').addEventListener(''click'', function () {
console.log(this); // This refers to the DOM element the eventListener was invoked from
})
document.querySelector(''.foo'').addEventListener(''click'', () => {
console.log(this); // Tip, es6 arrow function don''t have their own binding to the this v
}) // Therefore this will log the global object
.foo:hover {
color: red;
cursor: pointer;
}
<div class="foo">click me</div>
Constructor de ejemplo:
function Person (name) {
this.name = name;
}
const me = new Person(''Willem'');
// When using the new keyword the this in the constructor function will refer to the newly created object
console.log(me.name);
// Therefore, the name property was placed on the object created with new keyword.
"esto" tiene que ver con el alcance. Cada función tiene su propio alcance, y como todo en JS es un objeto, incluso una función puede almacenar algunos valores en sí misma usando "esto". OOP 101 enseña que "esto" solo es aplicable a instancias de un objeto. Por lo tanto, cada vez que se ejecuta una función, una nueva "instancia" de esa función tiene un nuevo significado de "esto".
La mayoría de las personas se confunden cuando intentan usar "esto" dentro de funciones de cierre anónimo como:
(function(value) { this.value = value; $(''.some-elements'').each(function(elt){ elt.innerHTML = this.value; // uh oh!! possibly undefined }); })(2);
Así que aquí, dentro de cada (), "esto" no contiene el "valor" que usted espera (de
this.value = value; sobre eso). Por lo tanto, para superar este problema (no es un juego de palabras), un desarrollador podría:
(function(value) { var self = this; // small change self.value = value; $(''.some-elements'').each(function(elt){ elt.innerHTML = self.value; // phew!! == 2 }); })(2);
Pruébalo; Comenzarás a gustarte este patrón de programación.
Recomiendo leer primero el artículo Scope en JavaScript ( mirror ) de Mike West . Es una excelente y amigable introducción a los conceptos de this
y las cadenas de alcance en JavaScript.
Una vez que empiezas a acostumbrarte a this
, las reglas son bastante simples. El estándar ECMAScript 5.1 define this
:
§11.1.1 La palabra clave
this
La palabra clave
this
evalúa con el valor de ThisBinding del contexto de ejecución actual
ThisBinding es algo que el intérprete de JavaScript mantiene cuando evalúa el código de JavaScript, como un registro de CPU especial que contiene una referencia a un objeto. El intérprete actualiza ThisBinding al establecer un contexto de ejecución en uno de solo tres casos diferentes:
1. Contexto de ejecución global inicial.
Este es el caso del código JavaScript que se evalúa en el nivel superior, por ejemplo, cuando está directamente dentro de un <script>
:
<script>
alert("I''m evaluated in the initial global execution context!");
setTimeout(function () {
alert("I''m NOT evaluated in the initial global execution context.");
}, 1);
</script>
Al evaluar el código en el contexto de ejecución global inicial, ThisBinding se establece en el objeto global, window
( §10.4.1.1 ).
Ingresando el codigo eval
... mediante una llamada directa a
eval()
ThisBinding no se modifica; es el mismo valor que ThisBinding del contexto de ejecución de llamada ( §10.4.2 (2) (a)).... si no es por una llamada directa a
eval()
ThisBinding se establece en el objeto global como si se ejecutara en el contexto de ejecución global inicial ( §10.4.2 (1)).
§15.1.2.1.1 define lo que es una llamada directa a eval()
. Básicamente, eval(...)
es una llamada directa, mientras que algo como (0, eval)(...)
o var indirectEval = eval; indirectEval(...);
var indirectEval = eval; indirectEval(...);
Es una llamada indirecta a eval()
. Ver la respuesta de chuckj a (1, eval) (''this'') vs eval (''this'') en JavaScript? y el ECMA-262-5 de Dmitry Soshnikov en detalle. Capítulo 2. Modo estricto. para cuando podrías usar una llamada eval()
indirecta.
Introducir código de función
Esto ocurre cuando se llama a una función. Si se llama a una función en un objeto, como en obj.myMethod()
o el equivalente obj["myMethod"]()
, ThisBinding se establece en el objeto ( obj
en el ejemplo; §13.2.1 ). En la mayoría de los otros casos, ThisBinding se establece en el objeto global ( §10.4.3 ).
La razón para escribir "en la mayoría de los otros casos" es porque hay ocho funciones incorporadas de ECMAScript 5 que permiten que ThisBinding se especifique en la lista de argumentos. Estas funciones especiales toman un llamado thisArg
que se convierte en ThisBinding al llamar a la función ( §10.4.3 ).
Estas funciones especiales incorporadas son:
-
Function.prototype.apply( thisArg, argArray )
-
Function.prototype.call( thisArg [ , arg1 [ , arg2, ... ] ] )
-
Function.prototype.bind( thisArg [ , arg1 [ , arg2, ... ] ] )
-
Array.prototype.every( callbackfn [ , thisArg ] )
-
Array.prototype.some( callbackfn [ , thisArg ] )
-
Array.prototype.forEach( callbackfn [ , thisArg ] )
-
Array.prototype.map( callbackfn [ , thisArg ] )
-
Array.prototype.filter( callbackfn [ , thisArg ] )
En el caso de las funciones Function.prototype
, se llaman en un objeto de función, pero en lugar de establecer ThisBinding en el objeto de función, ThisBinding se establece en thisArg
.
En el caso de las funciones Array.prototype
, se llama al callbackfn
dado en un contexto de ejecución donde ThisBinding se establece en thisArg
si se proporciona; De lo contrario, al objeto global.
Esas son las reglas de JavaScript simple. Cuando comienzas a usar bibliotecas de JavaScript (por ejemplo, jQuery), puedes encontrar que ciertas funciones de la biblioteca manipulan el valor de this
. Los desarrolladores de esas bibliotecas de JavaScript hacen esto porque tiende a admitir los casos de uso más comunes, y los usuarios de la biblioteca generalmente consideran que este comportamiento es más conveniente. Al pasar las funciones de devolución de llamada que hacen referencia a las funciones de la biblioteca, debe consultar la documentación para obtener garantías sobre el valor de this
cuando se llama a la función.
Si se está preguntando cómo una biblioteca de JavaScript manipula el valor de this
, la biblioteca simplemente está utilizando una de las funciones de JavaScript integradas que aceptan un thisArg
. Usted también puede escribir su propia función tomando una función de devolución de llamada y thisArg
:
function doWork(callbackfn, thisArg) {
//...
if (callbackfn != null) callbackfn.call(thisArg);
}
Hay un caso especial que aún no mencioné. Al construir un nuevo objeto a través del new
operador, el intérprete de JavaScript crea un nuevo objeto vacío, establece algunas propiedades internas y luego llama a la función de constructor en el nuevo objeto. Por lo tanto, cuando se llama a una función en un contexto de constructor, el valor de this
es el nuevo objeto que creó el intérprete:
function MyType() {
this.someData = "a string";
}
var instance = new MyType();
// Kind of like the following, but there are more steps involved:
// var instance = {};
// MyType.call(instance);
Sólo por diversión, prueba tu comprensión con algunos ejemplos.
Para revelar las respuestas, pase el mouse sobre los cuadros de color amarillo claro.
¿Cuál es el valor de
this
en la línea marcada? ¿Por qué?window
- La línea marcada se evalúa en el contexto de ejecución global inicial.if (true) { // What is `this` here? }
¿Cuál es el valor de
this
en la línea marcada cuando seobj.staticFunction()
? ¿Por qué?obj
: al llamar a una función en un objeto, ThisBinding se establece en el objeto.var obj = { someData: "a string" }; function myFun() { return this // What is `this` here? } obj.staticFunction = myFun; console.log("this is window:", obj.staticFunction() == window); console.log("this is obj:", obj.staticFunction() == obj);
¿Cuál es el valor de
this
en la línea marcada? ¿Por qué?window
En este ejemplo, el intérprete de JavaScript ingresa el código de función, pero dado que no se llama a
myFun
/obj.myMethod
en un objeto, ThisBinding se establece en lawindow
.Esto es diferente de Python, en el que el acceso a un método (
obj.myMethod
) crea un objeto de método enlazado .var obj = { myMethod: function () { return this; // What is `this` here? } }; var myFun = obj.myMethod; console.log("this is window:", myFun() == window); console.log("this is obj:", myFun() == obj);
¿Cuál es el valor de
this
en la línea marcada? ¿Por qué?window
Este fue complicado. Al evaluar el código de evaluación,
this
esobj
. Sin embargo, en el código eval,myFun
no se llama en un objeto, por lo que ThisBinding se establece en lawindow
para la llamada.function myFun() { return this; // What is `this` here? } var obj = { myMethod: function () { eval("myFun()"); } };
¿Cuál es el valor de
this
en la línea marcada? ¿Por qué?obj
La línea
myFun.call(obj);
está invocando la función incorporada especialFunction.prototype.call()
, que acepta athisArg
como el primer argumento.function myFun() { return this; // What is `this` here? } var obj = { someData: "a string" }; console.log("this is window:", myFun.call(obj) == window); console.log("this is obj:", myFun.call(obj) == obj);
Here hay una buena fuente de this
in JavaScript
.
Aquí está el resumen:
global esto
En un navegador, en el ámbito global, se
this
encuentra elwindow
objeto.<script type="text/javascript"> console.log(this === window); // true var foo = "bar"; console.log(this.foo); // "bar" console.log(window.foo); // "bar"
En el
node
uso de la respuesta,this
es el espacio de nombres superior. Puedes referirte a él comoglobal
.>this { ArrayBuffer: [Function: ArrayBuffer], Int8Array: { [Function: Int8Array] BYTES_PER_ELEMENT: 1 }, Uint8Array: { [Function: Uint8Array] BYTES_PER_ELEMENT: 1 }, ... >global === this true
Al
node
ejecutarse desde un script,this
en el ámbito global comienza como un objeto vacío. No es lo mismo queglobal
//test.js console.log(this); // {} console.log(this === global); // fasle
funciona este
Excepto en el caso de los controladores de eventos DOM o cuando thisArg
se proporciona una (ver más abajo), tanto en el nodo como en un navegador que utiliza this
una función que no se llama con new
referencias al alcance global ...
<script type="text/javascript">
foo = "bar";
function testThis() {
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
testThis();
console.log(this.foo); //logs "foo"
</script>
Si lo usas use strict;
, en cuyo caso this
seráundefined
<script type="text/javascript">
foo = "bar";
function testThis() {
"use strict";
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
testThis(); //Uncaught TypeError: Cannot set property ''foo'' of undefined
</script>
Si llama a una función con new
el this
que será un nuevo contexto, no hará referencia al global this
.
<script type="text/javascript">
foo = "bar";
function testThis() {
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
new testThis();
console.log(this.foo); //logs "bar"
console.log(new testThis().foo); //logs "foo"
</script>
- prototipo este
Las funciones que creas se convierten en objetos de función. Obtienen automáticamente una prototype
propiedad especial , que es algo a lo que puede asignar valores. Cuando creas una instancia llamando a tu función new
, obtendrás acceso a los valores que asignaste a la prototype
propiedad. Se accede a esos valores utilizando this
.
function Thing() {
console.log(this.foo);
}
Thing.prototype.foo = "bar";
var thing = new Thing(); //logs "bar"
console.log(thing.foo); //logs "bar"
Por lo general, es un error asignar matrices u objetos en el archivoprototype
. Si desea que las instancias tengan cada uno sus propios arreglos, créelos en la función, no en el prototipo.
function Thing() {
this.things = [];
}
var thing1 = new Thing();
var thing2 = new Thing();
thing1.things.push("foo");
console.log(thing1.things); //logs ["foo"]
console.log(thing2.things); //logs []
- objetar esto
Puede usar this
en cualquier función en un objeto para referirse a otras propiedades en ese objeto. Esto no es lo mismo que una instancia creada con new
.
var obj = {
foo: "bar",
logFoo: function () {
console.log(this.foo);
}
};
obj.logFoo(); //logs "bar"
- Evento DOM este
En un controlador de eventos HTML DOM, this
siempre es una referencia al elemento DOM al que se adjuntó el evento
function Listener() {
document.getElementById("foo").addEventListener("click",
this.handleClick);
}
Listener.prototype.handleClick = function (event) {
console.log(this); //logs "<div id="foo"></div>"
}
var listener = new Listener();
document.getElementById("foo").click();
A menos que tú bind
el contexto.
function Listener() {
document.getElementById("foo").addEventListener("click",
this.handleClick.bind(this));
}
Listener.prototype.handleClick = function (event) {
console.log(this); //logs Listener {handleClick: function}
}
var listener = new Listener();
document.getElementById("foo").click();
- HTML esto
Dentro de los atributos HTML en los que puede poner JavaScript, this
es una referencia al elemento.
<div id="foo" onclick="console.log(this);"></div>
<script type="text/javascript">
document.getElementById("foo").click(); //logs <div id="foo"...
</script>
- eval esta
Se puede utilizar eval
para acceder this
.
function Thing () {
}
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () {
eval("console.log(this.foo)"); //logs "bar"
}
var thing = new Thing();
thing.logFoo();
- con este
Puede usarlo with
para agregar this
al alcance actual para leer y escribir valores this
sin consultar this
explícitamente.
function Thing () {
}
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () {
with (this) {
console.log(foo);
foo = "foo";
}
}
var thing = new Thing();
thing.logFoo(); // logs "bar"
console.log(thing.foo); // logs "foo"
- jQuery esto
jQuery en muchos lugares se this
referirá a un elemento DOM.
<div class="foo bar1"></div>
<div class="foo bar2"></div>
<script type="text/javascript">
$(".foo").each(function () {
console.log(this); //logs <div class="foo...
});
$(".foo").on("click", function () {
console.log(this); //logs <div class="foo...
});
$(".foo").each(function () {
this.click();
});
</script>
this
en Javascript siempre se refiere al ''propietario'' de la función que se está ejecutando .
Si no se define un propietario explícito, se hace referencia al propietario más superior, el objeto de ventana.
Asi que si lo hice
function someKindOfFunction() {
this.style = ''foo'';
}
element.onclick = someKindOfFunction;
this
Se referiría al objeto objeto. Pero ten cuidado, mucha gente comete este error.
<element onclick="someKindOfFunction()">
En este último caso, simplemente hace referencia a la función, no se la entrega al elemento. Por lo tanto, this
se referirá al objeto de la ventana.
this
palabra clave se comporta de manera diferente en JavaScript en comparación con otro idioma. En lenguajes orientados a objetos, this
palabra clave se refiere a la instancia actual de la clase. En JavaScript, el valor de this
está determinado principalmente por el contexto de invocación de la función ( context.function()
) y dónde se llama.
1. Cuando se utiliza en contexto global
Cuando usa this
en un contexto global, está vinculado a un objeto global ( window
en el navegador)
document.write(this); //[object Window]
Cuando usa this
dentro de una función definida en el contexto global, this
todavía está vinculado al objeto global ya que la función se convierte en un método de contexto global.
function f1()
{
return this;
}
document.write(f1()); //[object Window]
Por encima de f1
se hace un método de objeto global. Por lo tanto, también podemos llamarlo en el objeto window
siguiente manera:
function f()
{
return this;
}
document.write(window.f()); //[object Window]
2. Cuando se usa dentro del método de objeto
Cuando utiliza this
palabra clave dentro de un método de objeto, this
está vinculado al objeto de encierro "inmediato".
var obj = {
name: "obj",
f: function () {
return this + ":" + this.name;
}
};
document.write(obj.f()); //[object Object]:obj
Arriba he puesto la palabra inmediata entre comillas dobles. Es para señalar que si anida el objeto dentro de otro objeto, entonces this
está vinculado al padre inmediato.
var obj = {
name: "obj1",
nestedobj: {
name:"nestedobj",
f: function () {
return this + ":" + this.name;
}
}
}
document.write(obj.nestedobj.f()); //[object Object]:nestedobj
Incluso si agrega la función explícitamente al objeto como un método, aún sigue las reglas anteriores, es decir, this
todavía apunta al objeto primario inmediato.
var obj1 = {
name: "obj1",
}
function returnName() {
return this + ":" + this.name;
}
obj1.f = returnName; //add method to object
document.write(obj1.f()); //[object Object]:obj1
3. Al invocar la función sin contexto.
Cuando utiliza this
función interna que se invoca sin ningún contexto (es decir, no en ningún objeto), está vinculada al objeto global ( window
en el navegador) (incluso si la función está definida dentro del objeto).
var context = "global";
var obj = {
context: "object",
method: function () {
function f() {
var context = "function";
return this + ":" +this.context;
};
return f(); //invoked without context
}
};
document.write(obj.method()); //[object Window]:global
Probando todo con funciones.
Podemos probar los puntos anteriores con funciones también. Sin embargo, hay algunas diferencias.
- Anteriormente agregamos miembros a objetos usando la notación literal de objetos. Podemos agregar miembros a las funciones usando
this
. para especificarlos. - La notación literal de objetos crea una instancia de objeto que podemos usar inmediatamente. Con la función podemos necesitar crear primero su instancia utilizando un
new
operador. - También en un enfoque de objeto literal, podemos agregar miembros explícitamente a objetos ya definidos usando el operador de puntos. Esto se agrega a la instancia específica solamente. Sin embargo, he agregado una variable al prototipo de la función para que se refleje en todas las instancias de la función.
A continuación, probé todas las cosas que hicimos con Object y this
arriba, pero primero creando una función en lugar de escribir directamente un objeto.
/*********************************************************************
1. When you add variable to the function using this keyword, it
gets added to the function prototype, thus allowing all function
instances to have their own copy of the variables added.
*********************************************************************/
function functionDef()
{
this.name = "ObjDefinition";
this.getName = function(){
return this+":"+this.name;
}
}
obj1 = new functionDef();
document.write(obj1.getName() + "<br />"); //[object Object]:ObjDefinition
/*********************************************************************
2. Members explicitly added to the function protorype also behave
as above: all function instances have their own copy of the
variable added.
*********************************************************************/
functionDef.prototype.version = 1;
functionDef.prototype.getVersion = function(){
return "v"+this.version; //see how this.version refers to the
//version variable added through
//prototype
}
document.write(obj1.getVersion() + "<br />"); //v1
/*********************************************************************
3. Illustrating that the function variables added by both above
ways have their own copies across function instances
*********************************************************************/
functionDef.prototype.incrementVersion = function(){
this.version = this.version + 1;
}
var obj2 = new functionDef();
document.write(obj2.getVersion() + "<br />"); //v1
obj2.incrementVersion(); //incrementing version in obj2
//does not affect obj1 version
document.write(obj2.getVersion() + "<br />"); //v2
document.write(obj1.getVersion() + "<br />"); //v1
/*********************************************************************
4. `this` keyword refers to the immediate parent object. If you
nest the object through function prototype, then `this` inside
object refers to the nested object not the function instance
*********************************************************************/
functionDef.prototype.nestedObj = { name: ''nestedObj'',
getName1 : function(){
return this+":"+this.name;
}
};
document.write(obj2.nestedObj.getName1() + "<br />"); //[object Object]:nestedObj
/*********************************************************************
5. If the method is on an object''s prototype chain, `this` refers
to the object the method was called on, as if the method was on
the object.
*********************************************************************/
var ProtoObj = { fun: function () { return this.a } };
var obj3 = Object.create(ProtoObj); //creating an object setting ProtoObj
//as its prototype
obj3.a = 999; //adding instance member to obj3
document.write(obj3.fun()+"<br />");//999
//calling obj3.fun() makes
//ProtoObj.fun() to access obj3.a as
//if fun() is defined on obj3
4. Cuando se utiliza dentro de la función de constructor .
Cuando la función se utiliza como un constructor (es decir, cuando se llama con una new
palabra clave), this
cuerpo interno de la función apunta al nuevo objeto que se está construyendo.
var myname = "global context";
function SimpleFun()
{
this.myname = "simple function";
}
var obj1 = new SimpleFun(); //adds myname to obj1
//1. `new` causes `this` inside the SimpleFun() to point to the
// object being constructed thus adding any member
// created inside SimipleFun() using this.membername to the
// object being constructed
//2. And by default `new` makes function to return newly
// constructed object if no explicit return value is specified
document.write(obj1.myname); //simple function
5. Cuando se utiliza dentro de la función definida en la cadena prototipo
Si el método está en la cadena de prototipo de un objeto, this
método interno se refiere al objeto en el que se invocó el método, como si el método estuviera definido en el objeto.
var ProtoObj = {
fun: function () {
return this.a;
}
};
//Object.create() creates object with ProtoObj as its
//prototype and assigns it to obj3, thus making fun()
//to be the method on its prototype chain
var obj3 = Object.create(ProtoObj);
obj3.a = 999;
document.write(obj3.fun()); //999
//Notice that fun() is defined on obj3''s prototype but
//`this.a` inside fun() retrieves obj3.a
6. Funciones internas de llamada (), aplicación () y vinculación ()
- Todos estos métodos se definen en
Function.prototype
. - Estos métodos permiten escribir una función una vez e invocarla en un contexto diferente. En otras palabras, permiten especificar el valor de
this
que se utilizará mientras se ejecuta la función. También toman cualquier parámetro para pasar a la función original cuando se invoca. -
fun.apply(obj1 [, argsArray])
Estableceobj1
como el valor dethis
fun()
internafun()
y llama afun()
pasar elementos deargsArray
como sus argumentos. -
fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])
- Estableceobj1
como el valor dethis
dentro defun()
y llamafun()
pasandoarg1, arg2, arg3, ...
como sus argumentos. -
fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])
- Devuelve la referencia a la funciónfun
conthis
diversión interna vinculada aobj1
y los parámetros deobj1
a los parámetros especificadosarg1, arg2, arg3,...
- Por ahora, la diferencia entre
apply
,call
ybind
debe haberse hecho evidente.apply
permite especificar los argumentos para funcionar como un objeto similar a una matriz, es decir, un objeto con una propiedad delength
numérica y sus correspondientes propiedades enteras no negativas. Mientras que lacall
permite especificar los argumentos a la función directamente. Tanto laapply
como lacall
invocan inmediatamente la función en el contexto especificado y con los argumentos especificados. Por otro lado, elbind
simplemente devuelve la función vinculada al valor especificado,this
y los argumentos. Podemos capturar la referencia a esta función devuelta asignándola a una variable y luego podemos llamarla en cualquier momento.
function add(inc1, inc2)
{
return this.a + inc1 + inc2;
}
var o = { a : 4 };
document.write(add.call(o, 5, 6)+"<br />"); //15
//above add.call(o,5,6) sets `this` inside
//add() to `o` and calls add() resulting:
// this.a + inc1 + inc2 =
// `o.a` i.e. 4 + 5 + 6 = 15
document.write(add.apply(o, [5, 6]) + "<br />"); //15
// `o.a` i.e. 4 + 5 + 6 = 15
var g = add.bind(o, 5, 6); //g: `o.a` i.e. 4 + 5 + 6
document.write(g()+"<br />"); //15
var h = add.bind(o, 5); //h: `o.a` i.e. 4 + 5 + ?
document.write(h(6) + "<br />"); //15
// 4 + 5 + 6 = 15
document.write(h() + "<br />"); //NaN
//no parameter is passed to h()
//thus inc2 inside add() is `undefined`
//4 + 5 + undefined = NaN</code>
7. this
dentro de los controladores de eventos
- Cuando asigna la función directamente a los controladores de eventos de un elemento, el uso de
this
directamente dentro de la función de manejo de eventos se refiere al elemento correspondiente. Dicha asignación de función directa se puede realizar utilizando el métodoaddeventListener
o mediante los métodos tradicionales de registro de eventos comoonclick
. - De manera similar, cuando usa
this
directamente dentro de la propiedad del evento (como<button onclick="...this..." >
) del elemento, se refiere al elemento. - Sin embargo, el uso de
this
indirectamente a través de la otra función llamada dentro de la función de manejo de eventos o propiedad de evento se resuelve en lawindow
objeto global. - El mismo comportamiento anterior se logra cuando adjuntamos la función al controlador de eventos usando el método de evento de registro de eventos de Microsoft. En lugar de asignar la función al controlador de eventos (y, por lo tanto, hacer el método de función del elemento), llama a la función en el evento (llamándola efectivamente en el contexto global).
Recomiendo probar mejor esto en JSFiddle .
<script>
function clickedMe() {
alert(this + " : " + this.tagName + " : " + this.id);
}
document.getElementById("button1").addEventListener("click", clickedMe, false);
document.getElementById("button2").onclick = clickedMe;
document.getElementById("button5").attachEvent(''onclick'', clickedMe);
</script>
<h3>Using `this` "directly" inside event handler or event property</h3>
<button id="button1">click() "assigned" using addEventListner() </button><br />
<button id="button2">click() "assigned" using click() </button><br />
<button id="button3" onclick="alert(this+ '' : '' + this.tagName + '' : '' + this.id);">used `this` directly in click event property</button>
<h3>Using `this` "indirectly" inside event handler or event property</h3>
<button onclick="alert((function(){return this + '' : '' + this.tagName + '' : '' + this.id;})());">`this` used indirectly, inside function <br /> defined & called inside event property</button><br />
<button id="button4" onclick="clickedMe()">`this` used indirectly, inside function <br /> called inside event property</button> <br />
IE only: <button id="button5">click() "attached" using attachEvent() </button>
this
es uno de los conceptos mal entendidos en JavaScript porque se comporta de manera diferente de un lugar a otro. Simplemente, se this
refiere al "propietario" de la función que estamos ejecutando actualmente .
this
ayuda a obtener el objeto actual (también conocido como contexto de ejecución) con el que trabajamos. Si entiende en qué objeto se está ejecutando la función actual, puede entender fácilmente qué corriente this
es
var val = "window.val"
var obj = {
val: "obj.val",
innerMethod: function () {
var val = "obj.val.inner",
func = function () {
var self = this;
return self.val;
};
return func;
},
outerMethod: function(){
return this.val;
}
};
//This actually gets executed inside window object
console.log(obj.innerMethod()()); //returns window.val
//Breakdown in to 2 lines explains this in detail
var _inn = obj.innerMethod();
console.log(_inn()); //returns window.val
console.log(obj.outerMethod()); //returns obj.val
Arriba creamos 3 variables con el mismo nombre ''val''. Uno en el contexto global, uno dentro de obj y el otro dentro de Método interno de obj. JavaScript resuelve los identificadores dentro de un contexto particular subiendo la cadena de alcance de local go global.
Pocos lugares donde this
diferenciarse.
Llamando a un método de un objeto
var status = 1;
var helper = {
status : 2,
getStatus: function () {
return this.status;
}
};
var theStatus1 = helper.getStatus(); //line1
console.log(theStatus1); //2
var theStatus2 = helper.getStatus;
console.log(theStatus2()); //1
Cuando se ejecuta la línea 1, JavaScript establece un contexto de ejecución (EC) para la llamada a la función, estableciendo this
el objeto al que hace referencia lo que vino antes del último "." .así que en la última línea puedes entender que a()
se ejecutó en el contexto global que es el window
.
Con constructor
this
Se puede utilizar para referirse al objeto que se está creando.
function Person(name){
this.personName = name;
this.sayHello = function(){
return "Hello " + this.personName;
}
}
var person1 = new Person(''Scott'');
console.log(person1.sayHello()); //Hello Scott
var person2 = new Person(''Hugh'');
var sayHelloP2 = person2.sayHello;
console.log(sayHelloP2()); //Hello undefined
Cuando Person()
se ejecuta nuevo, se crea un objeto completamente nuevo. Person
se llama y this
se establece para hacer referencia a ese nuevo objeto.
Llamada de función
function testFunc() {
this.name = "Name";
this.myCustomAttribute = "Custom Attribute";
return this;
}
var whatIsThis = testFunc();
console.log(whatIsThis); //window
var whatIsThis2 = new testFunc();
console.log(whatIsThis2); //testFunc() / object
console.log(window.myCustomAttribute); //Custom Attribute
Si perdemos la new
palabra clave, se whatIsThis
refiere al contexto más global que puede encontrar ( window
)
Con manejadores de eventos
Si el controlador de eventos está en línea, se this
refiere al objeto global
<script type="application/javascript">
function click_handler() {
alert(this); // alerts the window object
}
</script>
<button id=''thebutton'' onclick=''click_handler()''>Click me!</button>
Cuando se agrega un controlador de eventos a través de JavaScript, se this
refiere al elemento DOM que generó el evento.
- También puedes manipular el contexto usando
.apply()
.call()
y.bind()
- El proxy JQuery es otra forma que puede usar para asegurarse de que esto en una función sea el valor que desea. (Verifique que comprenda $ .proxy () , jQuery.proxy () uso )
- Qué
var that = this
significa en JavaScript
Dado que este hilo se ha incrementado, he recopilado algunos puntos para lectores nuevos en el this
tema.
¿Cómo se this
determina el valor de ?
Utilizamos esta similar a la forma en que usamos los pronombres en las lenguas naturales como el Inglés: “Juan está ejecutando rápido porque él está tratando de coger el tren.” En cambio, nos podríamos haber escrito “... John está tratando de coger el tren”.
var person = {
firstName: "Penelope",
lastName: "Barrymore",
fullName: function () {
// We use "this" just as in the sentence above:
console.log(this.firstName + " " + this.lastName);
// We could have also written:
console.log(person.firstName + " " + person.lastName);
}
}
this
no se le asigna un valor hasta que un objeto invoca la función donde está definido. En el ámbito global, todas las variables y funciones globales se definen en el window
objeto. Por lo tanto, this
en una función global se refiere a (y tiene el valor de) el window
objeto global .
Cuando use strict
, this
en funciones globales y anónimas que no están vinculadas a ningún objeto, tiene un valor de undefined
.
La this
palabra clave se entiende mejor cuando: 1) tomamos prestado un método que usa this
, 2) asignamos un método que usa this
una variable, 3) una función que usa this
se pasa como una función de devolución de llamada, y 4) this
se usa dentro de un cierre: Una función interior. (2)
Lo que depara el futuro
Definidas en ECMA Script 6 , las funciones de flecha adoptan el this
enlace desde el ámbito adjunto (función o global).
function foo() {
// return an arrow function
return (a) => {
// `this` here is lexically inherited from `foo()`
console.log(this.a);
};
}
var obj1 = { a: 2 };
var obj2 = { a: 3 };
var bar = foo.call(obj1);
bar.call( obj2 ); // 2, not 3!
Si bien las funciones de flecha proporcionan una alternativa al uso bind()
, es importante tener en cuenta que esencialmente están inhabilitando el this
mecanismo tradicional en favor de un alcance léxico más comprendido. (1)
Referencias:
- esto y prototipos de objetos , por Kyle Simpson. © 2014 Getify Solutions.
- javascriptissexy.com - http://goo.gl/pvl0GX
- Angus Croll - http://goo.gl/Z2RacU
este uso para Scope como este
<script type="text/javascript" language="javascript">
$(''#tbleName tbody tr'').each(function{
var txt='''';
txt += $(this).find("td").eq(0).text();
//same as above but synatx different
var txt1='''';
txt1+=$(''#tbleName tbody tr'').eq(0).text();
alert(txt1)
});
</script>
el valor de txt1 y txt es igual en el ejemplo anterior $ (this) = $ (''# tbleName tbody tr'') es igual
¿A qué ayudaría quirksmode.org/js/this.html ? (La mayor parte de la confusión de ''esto'' en javascript proviene del hecho de que generalmente no está vinculado a su objeto, sino al ámbito de ejecución actual, que puede que no sea exactamente la forma en que funciona, pero siempre se siente así para mí. ver el artículo para una explicación completa)
Cada contexto de ejecución de función en javascript tiene un contexto de alcance, este parámetro está establecido por:
- Cómo se llama la función (incluido como método de objeto, uso de call y apply , uso de nuevo )
- Uso de enlace
- Léxicamente para funciones de flecha (adoptan esto de su contexto de ejecución externo)
Cualquiera que sea el contexto de alcance, está referenciado por "esto".
Puede cambiar el valor de este contexto de alcance usando , o .func.call
func.apply
func.bind
De forma predeterminada, y lo que confunde a la mayoría de los principiantes, cuando se llama a un detector de devolución de llamada después de que se genera un evento en un elemento DOM, el contexto de alcance de este valor de la función es el elemento DOM.
jQuery hace que esto sea trivial para cambiar con jQuery.proxy.
Daniel, impresionante explicación! Un par de palabras sobre esta y una buena lista de this
punteros de contexto de ejecución en caso de manejadores de eventos.
En dos palabras, this
en JavaScript señala el objeto desde el cual (o desde cuyo contexto de ejecución) se ejecutó la función actual y siempre es de solo lectura, no puede configurarlo de todos modos (tal intento terminará con ''Mano izquierda no válida Lado en el mensaje de asignación.
Para los manejadores de eventos: los manejadores de eventos en línea, como <element onclick="foo">
anular cualquier otro manejador adjunto anteriormente y antes, así que tenga cuidado y es mejor evitar la delegación de eventos en línea. Y gracias a Zara Alaverdyan, que me inspiró a esta lista de ejemplos a través de un debate disidente :)
-
el.onclick = foo; // in the foo - obj
-
el.onclick = function () {this.style.color = ''#fff'';} // obj
-
el.onclick = function() {doSomething();} // In the doSomething - Window
-
el.addEventListener(''click'',foo,false) // in the foo - obj
-
el.attachEvent(''onclick, function () { // this }'') // window, all the compliance to IE :)
-
<button onclick="this.style.color = ''#fff'';"> // obj
-
<button onclick="foo"> // In the foo - window, but you can <button onclick="foo(this)">
El valor de "esto" depende del "contexto" en el que se ejecuta la función. El contexto puede ser cualquier objeto o el objeto global, es decir, la ventana.
Así que la Semántica de "esto" es diferente de los lenguajes tradicionales OOP. Y causa problemas: 1. cuando una función se pasa a otra variable (lo más probable, una devolución de llamada); y 2. cuando se invoca un cierre desde un método miembro de una clase.
En ambos casos, esto se establece en ventana.
En términos pseudoclásicos, la forma en que muchas conferencias enseñan la palabra clave ''this'' es como un objeto creado por una clase o un constructor de objetos. Cada vez que se construye un nuevo objeto a partir de una clase, imagine que bajo el capó se crea y devuelve una instancia local de un objeto ''this''. Recuerdo que enseñaba así:
function Car(make, model, year) {
var this = {}; // under the hood, so to speak
this.make = make;
this.model = model;
this.year = year;
return this; // under the hood
}
var mycar = new Car(''Eagle'', ''Talon TSi'', 1993);
// ========= under the hood
var this = {};
this.make = ''Eagle'';
this.model = ''Talon TSi'';
this.year = 1993;
return this;
Es difícil tener un buen conocimiento de JS, o escribir más que cualquier cosa trivial, si no lo entiendes bien. No puede darse el lujo de darse un baño rápido :) Creo que la mejor manera de comenzar con JS es ver primero estas conferencias de video de Douglas Crockford - http://yuiblog.com/crockford/ , que cubre esto y aquello, Todo lo demás sobre JS.
Esta es la mejor explicación que he visto. Entender JavaScripts esto con claridad
El esta referencia se refiere a SIEMPRE (y mantiene el valor de) un objeto-a singular objeto-y se utiliza por lo general dentro de una función o un método, aunque se puede utilizar fuera de una función en el ámbito global. Tenga en cuenta que cuando usamos el modo estricto, esto mantiene el valor de indefinido en funciones globales y en funciones anónimas que no están vinculadas a ningún objeto.
Hay cuatro condiciones donde esto puede ser confuso:
- Cuando pasamos un método (que usa esto ) como un parámetro para ser usado como una función de devolución de llamada.
- Otra instancia en la que esto se malinterpreta es cuando usamos un método interno (un cierre). Es importante tener en cuenta que los cierres no pueden acceder a la función externa de esta variable mediante el uso de esta palabra clave porque esta variable es accesible solo por la función en sí, no por las funciones internas.
- Usando esto cuando se asigna un método a una variable. El valor de este está vinculado a otro objeto, si asignamos un método que usa esto a una variable
- Usando esto al usar los métodos de enlazar, aplicar y llamar.
Da ejemplos de código, las explicaciones y las correcciones de código que me parecieron muy útiles.
Existe mucha confusión con respecto a cómo se interpreta la palabra clave "this" en JavaScript. Esperemos que este artículo ponga a todos a descansar de una vez por todas. Y mucho más. Por favor, lea todo el artículo cuidadosamente. Tenga en cuenta que este artículo es largo.
Independientemente del contexto en el que se usa, "esto" siempre hace referencia al "objeto actual" en Javascript. Sin embargo, el "objeto actual" difiere según el contexto . El contexto puede ser exactamente 1 de los 6 siguientes:
- Global (es decir, fuera de todas las funciones)
- Llamada interna directa de " función no vinculada " (es decir, una función que no se ha vinculado al llamar a functionName.bind )
- Llamada interna indirecta "Función no vinculada" a través de functionName.call y functionName.apply
- Dentro de la llamada "Función enlazada " (es decir, una función que se ha enlazado al llamar a functionName.bind )
- Si bien la creación de objetos a través de "nuevo"
- Controlador de eventos Inside Inline DOM
Lo siguiente describe cada uno de estos contextos uno por uno:
Contexto global (es decir, fuera de todas las funciones):
Fuera de todas las funciones (es decir, en el contexto global), el "objeto actual" (y, por lo tanto, el valor de "este" ) es siempre el objeto "ventana" para los navegadores.
Llamada "Función no vinculada" directa interna :
Dentro de una llamada directa de "función no vinculada" directa, el objeto que invocó la llamada de función se convierte en el "objeto actual" (y, por lo tanto, el valor de "este" ). Si se llama a una función sin un objeto actual explícito , el objeto actual es el objeto "ventana" (para el modo no estricto) o indefinido (para el modo estricto). Cualquier función (o variable) definida en el contexto global se convierte automáticamente en una propiedad del objeto "ventana". Por ejemplo, la función Suppose se define en el contexto global como
function UserDefinedFunction(){ alert(this) }
se convierte en propiedad del objeto de ventana, como si lo hubiera definido como
window.UserDefinedFunction=function(){ alert(this) }
En el "Modo no estricto", Llamar / Invocar esta función directamente a través de "UserDefinedFunction ()" automáticamente lo llamará / invocará como "window.UserDefinedFunction ()" making "window" como el "objeto actual" (y por lo tanto el valor de " este " ) dentro de " UserDefinedFunction ". Invocar esta función en" Modo no estricto "resultará en lo siguiente
UserDefinedFunction() // displays [object Window] as it automatically gets invoked as window.UserDefinedFunction()
En "Modo estricto", Calling / invocación de la función directamente a través de "UserDefinedFunction ()" será "NO" llamar automáticamente / invocar como "window.UserDefinedFunction ()" .Hence el "objeto actual" (y el valor de "este" ) dentro de "UserDefinedFunction" será indefinido . Invocar esta función en "Modo estricto" dará como resultado lo siguiente
UserDefinedFunction() // displays undefined
Sin embargo, invocarlo explícitamente usando el objeto de ventana dará como resultado lo siguiente:
window.UserDefinedFunction() // "always displays [object Window] irrespective of mode."
Veamos otro ejemplo. Por favor mira el siguiente código
function UserDefinedFunction() { alert(this.a + "," + this.b + "," + this.c + "," + this.d) } var o1={ a:1, b:2, f:UserDefinedFunction } var o2={ c:3, d:4, f:UserDefinedFunction } o1.f() // Shall display 1,2,undefined,undefined o2.f() // Shall display undefined,undefined,3,4
En el ejemplo anterior, vemos que cuando se invocó "UserDefinedFunction" a través de o1 , "this" toma el valor de o1 y el valor de sus propiedades "a" y "b" se muestran. El valor de "c" y "d" se mostraron como no definidos ya que o1 no define estas propiedades
Del mismo modo, cuando "UserDefinedFunction" fue invocada a través de o2 , "este" toma el valor de O2 y el valor de sus propiedades "c" y "d" obtener displayed.The valor de "a" y "b" se muestra como indefinido como o2 hace No define estas propiedades.
Llamada interna indirecta "Función no vinculada" a través de functionName.call y functionName.apply :
Cuando se llama a una "función no vinculada" a través de functionName.call o functionName.apply , el "objeto actual" (y, por tanto, el valor de "this" ) se establece en el valor de "this" parámetro (primer parámetro) pasado a la llamada / aplicar . El siguiente código demuestra lo mismo.
function UserDefinedFunction() { alert(this.a + "," + this.b + "," + this.c + "," + this.d) } var o1={ a:1, b:2, f:UserDefinedFunction } var o2={ c:3, d:4, f:UserDefinedFunction } UserDefinedFunction.call(o1) // Shall display 1,2,undefined,undefined UserDefinedFunction.apply(o1) // Shall display 1,2,undefined,undefined UserDefinedFunction.call(o2) // Shall display undefined,undefined,3,4 UserDefinedFunction.apply(o2) // Shall display undefined,undefined,3,4 o1.f.call(o2) // Shall display undefined,undefined,3,4 o1.f.apply(o2) // Shall display undefined,undefined,3,4 o2.f.call(o1) // Shall display 1,2,undefined,undefined o2.f.apply(o1) // Shall display 1,2,undefined,undefined
El código anterior muestra claramente que el valor de "este" para cualquier "función no vinculada" puede modificarse mediante call / apply . Además, si el parámetro "this" no se pasa explícitamente a call / apply , "objeto actual" (y, por lo tanto, el valor de "this") se establece en "window" en modo no estricto y "indefinido" en modo estricto.
Dentro de la llamada "Función enlazada " (es decir, una función que se ha enlazado al llamar a functionName.bind ):
Una función enlazada es una función cuyo valor "esto" se ha corregido. El siguiente código demostró cómo "esto" funciona en caso de función vinculada
function UserDefinedFunction() { alert(this.a + "," + this.b + "," + this.c + "," + this.d) } var o1={ a:1, b:2, f:UserDefinedFunction, bf:null } var o2={ c:3, d:4, f:UserDefinedFunction, bf:null } var bound1=UserDefinedFunction.bind(o1); // permanantly fixes "this" value of function "bound1" to Object o1 bound1() // Shall display 1,2,undefined,undefined var bound2=UserDefinedFunction.bind(o2); // permanantly fixes "this" value of function "bound2" to Object o2 bound2() // Shall display undefined,undefined,3,4 var bound3=o1.f.bind(o2); // permanantly fixes "this" value of function "bound3" to Object o2 bound3() // Shall display undefined,undefined,3,4 var bound4=o2.f.bind(o1); // permanantly fixes "this" value of function "bound4" to Object o1 bound4() // Shall display 1,2,undefined,undefined o1.bf=UserDefinedFunction.bind(o2) // permanantly fixes "this" value of function "o1.bf" to Object o2 o1.bf() // Shall display undefined,undefined,3,4 o2.bf=UserDefinedFunction.bind(o1) // permanantly fixes "this" value of function "o2.bf" to Object o1 o2.bf() // Shall display 1,2,undefined,undefined bound1.call(o2) // Shall still display 1,2,undefined,undefined. "call" cannot alter the value of "this" for bound function bound1.apply(o2) // Shall still display 1,2,undefined,undefined. "apply" cannot alter the value of "this" for bound function o2.bf.call(o2) // Shall still display 1,2,undefined,undefined. "call" cannot alter the value of "this" for bound function o2.bf.apply(o2) // Shall still display 1,2,undefined,undefined."apply" cannot alter the value of "this" for bound function
Como se indica en el código anterior, "este" valor para cualquier "Función enlazada" NO SE PUEDE alterar a través de call / apply . Además, si el parámetro "esto" no se pasa explícitamente a vincular, el "objeto actual" (y, por lo tanto, el valor de "esto" ) se establece en "ventana" en el modo no estricto y "no definido" en el modo estricto. Una cosa más. El enlace de una función ya enlazada no cambia el valor de "esto" . Permanece establecido como el valor establecido por la primera función de enlace.
Si bien la creación de objetos a través de "nuevo" :
Dentro de una función constructora, el "objeto actual" (y, por tanto, el valor de "este" ) hace referencia al objeto que se está creando actualmente a través de "nuevo" independientemente del estado de enlace de la función. Sin embargo, si el constructor es una función vinculada, se llamará con un conjunto predefinido de argumentos según lo establecido para la función vinculada.
Dentro del controlador de eventos Inline DOM :
Por favor, mire el siguiente fragmento de código HTML
<button onclick=''this.style.color=white''>Hello World</button> <div style=''width:100px;height:100px;'' onclick=''OnDivClick(event,this)''>Hello World</div>
El "esto" en los ejemplos anteriores se refiere al elemento "botón" y al elemento "div" respectivamente.
En el primer ejemplo, el color de fuente del botón se establecerá en blanco cuando se haga clic en él.
En el segundo ejemplo, cuando se hace clic en el elemento "div" , se llamará a la función OnDivClick y su segundo parámetro hará referencia al elemento div en el que se hizo clic. Sin embargo, el valor de "esto" en OnDivClick NO DEBE hacer referencia al elemento div en el que se hizo clic . Se establecerá como "objeto de ventana" o "indefinido" en los modos no estricto y estricto respectivamente (si OnDivClick es una función independiente ) o se establecerá en un valor de límite predefinido (si OnDivClick es una función vinculada )
A continuación se resume todo el artículo.
En el contexto global, "esto" siempre se refiere al objeto "ventana"
Cuando se invoca una función, se invoca en el contexto de un objeto ( "objeto actual" ). Si el objeto actual no se proporciona explícitamente, el objeto actual es el "objeto de ventana" en el Modo NO Estricto y "no definido" en el Modo Estricto de manera predeterminada.
El valor de "esto" dentro de una función no vinculada es la referencia al objeto en el contexto de la cual se invoca la función ( "objeto actual" )
El valor de "esto" dentro de una función no vinculada puede ser anulado por los métodos de llamada y aplicación de la función.
El valor de "esto" es fijo para una función enlazada y no puede ser anulado por los métodos de llamada y aplicación de la función.
La función de vinculación y ya enlazada no cambia el valor de "esto". Permanece establecido como el valor establecido por la primera función de enlace.
El valor de "esto" dentro de un constructor es el objeto que se está creando e inicializando.
El valor de "esto" dentro de un controlador de eventos DOM en línea es referencia al elemento para el cual se proporciona el controlador de eventos.
Probablemente el artículo más detallado y completo sobre this
es el siguiente:
Explicación suave de la palabra clave ''this'' en JavaScript
La idea subyacente this
es comprender que los tipos de invocación de funciones tienen una importancia significativa en la configuración del this
valor.
Cuando tengas problemas para identificarte this
, no te preguntes:
¿De dónde se
this
toma ?
pero no preguntarse:
¿Cómo se invoca la función ?
Para una función de flecha (caso especial de transparencia de contexto) pregúntese:
¿Qué valor tiene
this
donde se define la función de flecha ?
Esta mentalidad es correcta cuando se trata con this
y te salvará del dolor de cabeza.
Un poco de información sobre esta palabra clave.
Registremos la this
palabra clave en la consola en el ámbito global sin más código, pero
console.log(this)
En la palabra clave Cliente / Navegador this
es un objeto global que eswindow
console.log(this === window) // true
y
En el servidor / Nodo / Javascript, la this
palabra clave de tiempo de ejecución también es un objeto global que esmodule.exports
console.log(this === module.exports) // true
console.log(this === exports) // true
Tener en cuenta exports
es sólo una referencia amodule.exports