6.1 KiB
title | localeTitle |
---|---|
this reference | esta referencia |
this
referencia
En JavaScript, cada función tiene this
referencia creada automáticamente cuando la declara. Esta referencia es bastante similar a this
referencia en otros lenguajes basados en clases como Java o C # (JavaScript es un lenguaje basado en prototipos y no tiene un concepto de "clase"): apunta al objeto que está llamando a la función (este objeto a veces llamado como contexto ). Sin embargo, en JavaScript, this
referencia dentro de las funciones puede vincularse a diferentes objetos dependiendo de dónde se llame la función . Aquí hay 5 reglas básicas para this
enlace en JavaScript:
Regla 1
Cuando se llama a una función en el ámbito global, this
referencia está vinculada por defecto al objeto global ( window
en el navegador o global
en Node.js). Por ejemplo:
function foo() {
this.a = 2;
}
foo();
console.log(a); // 2
Nota: Si se declara la foo()
función anterior en modo estricto, a continuación, se llama a esta función en el ámbito global, this
será undefined
y asignación this.a = 2
tirará Uncaught TypeError
excepción.
Regla 2
Examinemos el siguiente ejemplo:
function foo() {
this.a = 2;
}
var obj = {
foo: foo
};
obj.foo();
console.log(obj.a); // 2
Claramente, en el fragmento de código anterior, la función foo()
se llama con context es el objeto obj
y this
referencia ahora está vinculada a obj
. Entonces, cuando se llama a una función con un objeto de contexto, this
referencia se vinculará a este objeto.
Regla 3
.call
, .apply
y .bind
pueden usarse en el sitio de la llamada para enlazar explícitamente this
. Usar .bind(this)
es algo que puede ver en muchos componentes de React.
var foo = function() {
console.log(this.bar)
}
foo.call({ bar: 1 }) // 1
Aquí hay un ejemplo rápido de cómo se usa cada uno para unir this
:
.call()
:fn.call(thisObj, fnParam1, fnParam2)
.apply()
:fn.apply(thisObj, [fnParam1, fnParam2])
.bind()
:const newFn = fn.bind(thisObj, fnParam1, fnParam2)
Regla 4
function Point2D(x, y) {
this.x = x;
this.y = y;
}
var p1 = new Point2D(1, 2);
console.log(p1.x); // 1
console.log(p1.y); // 2
Lo que debe notar es la función Point2D
llamada con una new
palabra clave, y this
referencia está vinculada al objeto p1
. Entonces, cuando se llama a una función con una new
palabra clave, se creará un nuevo objeto y this
referencia se vinculará a este objeto.
Nota: al llamar a una función con una new
palabra clave, también la llamamos función constructora .
Regla 5
JavaScript determina el valor de this
en tiempo de ejecución, según el contexto actual. Entonces, this
veces puede apuntar a algo distinto de lo que esperas.
Considere este ejemplo de una clase Cat con un método llamado makeSound()
, siguiendo el patrón en la Regla 4 (arriba) con una función constructora y la new
palabra clave.
var Cat = function(name, sound) {
this.name = name;
this.sound = sound;
this.makeSound = function() {
console.log( this.name + ' says: ' + this.sound );
};
}
var kitty = new Cat('Fat Daddy', 'Mrrooowww');
kitty.makeSound(); // Fat Daddy says: Mrrooowww
Ahora tratemos de darle al gato una manera de annoy()
personas repitiendo su sonido 100 veces, una vez cada medio segundo.
var Cat = function(name, sound) {
this.name = name;
this.sound = sound;
this.makeSound = function() {
console.log( this.name + ' says: ' + this.sound );
};
this.annoy = function() {
var count = 0, max = 100;
var t = setInterval(function() {
this.makeSound(); // <-- this line fails with `this.makeSound is not a function`
count++;
if (count === max) {
clearTimeout(t);
}
}, 500);
};
}
var kitty = new Cat('Fat Daddy', 'Mrrooowww');
kitty.annoy();
Eso no funciona porque dentro de la setInterval
llamada setInterval
hemos creado un nuevo contexto con alcance global, por lo que this
ya no apunta a nuestra instancia de Kitty. En un navegador web, this
apuntará al objeto Window, que no tiene un método makeSound()
.
Un par de maneras de hacerlo funcionar:
- Antes de crear el nuevo contexto, asigne
this
a una variable local llamadame
, oself
, o como se llame, y use esa variable dentro de la devolución de llamada.
var Cat = function(name, sound) {
this.name = name;
this.sound = sound;
this.makeSound = function() {
console.log( this.name + ' says: ' + this.sound );
};
this.annoy = function() {
var count = 0, max = 100;
var self = this;
var t = setInterval(function() {
self.makeSound();
count++;
if (count === max) {
clearTimeout(t);
}
}, 500);
};
}
var kitty = new Cat('Fat Daddy', 'Mrrooowww');
kitty.annoy();
- Con ES6 puede evitar la asignación de
this
a una variable local mediante el uso de una función de flecha, que se unethis
con el contexto del código que rodea donde se define.
var Cat = function(name, sound) {
this.name = name;
this.sound = sound;
this.makeSound = function() {
console.log( this.name + ' says: ' + this.sound );
};
this.annoy = function() {
var count = 0, max = 100;
var t = setInterval(() => {
this.makeSound();
count++;
if (count === max) {
clearTimeout(t);
}
}, 500);
};
}
var kitty = new Cat('Fat Daddy', 'Mrrooowww');
kitty.annoy();