Hola Habr! Les presento la traducci贸n del art铆culo
"Qu茅 hacer cuando" esto "pierde contexto" por
Cristi Salcescu .
La mejor manera de evitar perder
este contexto es no usarlo. Sin embargo, esto no siempre es posible. Por ejemplo, trabajamos con el c贸digo o la biblioteca de otra persona que usa
esto .
Literal de objeto, funci贸n de constructor, constructor de objeto de clase en el sistema prototipo. Este pseudopar谩metro
se utiliza en el sistema de creaci贸n de prototipos para dar acceso a las propiedades del objeto.
Veamos algunos casos.
Funciones anidadas
esto pierde la referencia de contexto dentro de las funciones anidadas.
class Service { constructor(){ this.numbers = [1,2,3]; this.token = "token"; } doSomething(){ setTimeout(function doAnotherThing(){ this.numbers.forEach(function log(number){
El m茅todo
doSomething () tiene dos funciones anidadas:
doAnotherthing () y
log () . Al llamar a
service.doSomething () ,
esto pierde la referencia de contexto en la funci贸n anidada.
bind ()
Una forma de resolver el problema es con el m茅todo
bind () . Echa un vistazo al siguiente c贸digo:
doSomething(){ setTimeout(function doAnotherThing(){ this.numbers.forEach(function log(number){ console.log(number); console.log(this.token); }.bind(this)); }.bind(this), 100); }
bind () crea una nueva versi贸n de la funci贸n, que cuando se llama ya tiene un cierto valor de
esto .
La funci贸n doAnotherThing () {/*...*/}.bind(this) crea una versi贸n de la funci贸n
doAnotherThing () , que toma el valor de
esto de
doSomething () .
eso / yo
Otra opci贸n es declarar y usar la nueva variable
that / self , que almacenar谩
este valor del m茅todo
doSomething () .
doSomething(){ let that = this; setTimeout(function doAnotherThing(){ that.numbers.forEach(function log(number){ console.log(number); console.log(that.token); }); }, 100); }
Debemos declarar
let that = this en todos los m茅todos que usan
esto en funciones anidadas.
Funciones de flecha
La funci贸n de flecha nos da otra forma de resolver este problema.
doSomething(){ setTimeout(() => { this.numbers.forEach(number => { console.log(number); console.log(this.token); }); }, 100); }
Las funciones de flecha no crean su propio contexto para
esto , sino que usan el valor
this del contexto circundante. En el ejemplo anterior, usa el valor de
esto de la funci贸n padre.
La desventaja de este m茅todo es que no podemos especificar el nombre de la funci贸n de flecha. El nombre de la funci贸n juega un papel importante, ya que aumenta la legibilidad del c贸digo y describe su prop贸sito.
A continuaci贸n se muestra el mismo c贸digo con una funci贸n expresada en t茅rminos de un nombre de variable:
doSomething(){ let log = number => { console.log(number); console.log(this.token); } let doAnotherThing = () => { this.numbers.forEach(log); } setTimeout(doAnotherThing, 100); }
Funciones de devoluci贸n de llamada (M茅todo como devoluci贸n de llamada)
esto pierde referencia de contexto cuando se usa el m茅todo como una funci贸n de devoluci贸n de llamada. Veamos la siguiente clase:
class Service { constructor(){ this.token = "token"; } doSomething(){ console.log(this.token);
Veamos situaciones en las que el m茅todo
service.doSomething () se usa como una funci贸n de devoluci贸n de llamada.
En todos los casos anteriores,
esto pierde el enlace de contexto.
bind ()
Podemos usar
bind () para resolver este problema. A continuaci贸n se muestra el c贸digo para esta opci贸n:
Funci贸n de flecha
Otra forma es crear una funci贸n de flecha que llame a
service.doSomething () .
Reaccionar componentes
En los componentes,
esto pierde referencia de contexto cuando los m茅todos se usan como devoluciones de llamada para eventos.
class TodoAddForm extends React.Component { constructor(){ super(); this.todos = []; } componentWillMount() { this.setState({desc: ""}); } add(){ let todo = {desc: this.state.desc};
Como soluci贸n, podemos crear nuevas funciones en el constructor que usar谩n
bind (this) .
constructor(){ super(); this.todos = []; this.handleChange = this.handleChange.bind(this); this.add = this.add.bind(this); }
No use "esto"
No
esto , no hay problemas con la p茅rdida de contexto. Los objetos se pueden crear utilizando
funciones de f谩brica . Echa un vistazo a este ejemplo:
function Service() { let numbers = [1,2,3]; let token = "token"; function doSomething(){ setTimeout(function doAnotherThing(){ numbers.forEach(function log(number){ console.log(number); console.log(token); }); }, 100); } return Object.freeze({ doSomething }); }
El contexto permanece si usa el m茅todo como devoluci贸n de llamada.
let service = Service(); service.doSomething();
Conclusi贸n
esto pierde referencia de contexto en varias situaciones.
bind () , usando
esa variable
/ self y las funciones de flecha son formas de resolver problemas de contexto.
Las funciones de f谩brica permiten crear objetos sin usar
esto .