tutorial soljson smart remix org optimize online false español curso 59dbf8f1 javascript node.js promise this q

javascript - soljson - ¿Por qué ''esto'' no está definido dentro del método de clase cuando se usan promesas?



smart contracts ethereum (4)

Básicamente, le está pasando una referencia de función sin referencia de contexto. this contexto se determina de varias maneras:

  1. Implícitamente. Llamar a una función global o una función sin un enlace supone un contexto global. *
  2. Por referencia directa. Si llama a myObj.f() entonces myObj será el contexto de this . **
  3. Encuadernación manual. Esta es su clase de funciones como .bind y .apply . En estos se indica explícitamente cuál es el contexto. Estos siempre tienen prioridad sobre los dos anteriores.

En su ejemplo, está pasando una referencia de función, por lo que en su invocación se supone que es una función global o una sin contexto. El uso de .bind resuelve esto creando una nueva función donde se establece explícitamente.

* Esto solo es cierto en modo no estricto. En modo estricto, this está configurado como undefined .

** Suponiendo que la función que está utilizando no se ha vinculado manualmente.

Esta pregunta ya tiene una respuesta aquí:

Tengo una clase javascript y cada método devuelve una promesa Q Quiero saber por qué this no está definido en method2 y method3 . ¿Hay una forma más correcta de escribir este código?

function MyClass(opts){ this.options = opts; return this.method1() .then(this.method2) .then(this.method3); } MyClass.prototype.method1 = function(){ // ...q stuff... console.log(this.options); // logs "opts" object return deferred.promise; }; MyClass.prototype.method2 = function(method1resolve){ // ...q stuff... console.log(this); // logs undefined return deferred.promise; }; MyClass.prototype.method3 = function(method2resolve){ // ...q stuff... console.log(this); // logs undefined return deferred.promise; };

Puedo arreglar esto usando bind :

function MyClass(opts){ this.options = opts; return this.method1() .then(this.method2.bind(this)) .then(this.method3.bind(this)); }

Pero no del todo seguro por qué es necesario el bind ; ¿Está .then() matando this ?


Los manejadores de promesas se llaman en el contexto del objeto global ( window ) de forma predeterminada. Cuando está en modo estricto ( use strict; ), el contexto undefined está undefined . Esto es lo que le está sucediendo a method2 y method3 .

;(function(){ ''use strict'' Promise.resolve(''foo'').then(function(){console.log(this)}); // undefined }()); ;(function(){ Promise.resolve(''foo'').then(function(){console.log(this)}); // window }());

Para el method1 , está llamando al this.method1() como this.method1() . Esta forma de llamarlo lo llama en el contexto del objeto this que es su instancia. Es por eso que el contexto dentro de method1 es la instancia.


Una forma en que las funciones obtienen su contexto ( this ) es del objeto en el que se invocan (razón por la cual method1 tiene el contexto correcto, se invoca en this ). Está pasando una referencia a la función en sí para then . Puedes imaginar que la implementación de then ve así:

function then( callback ) { // assume ''value'' is the recently-fulfilled promise value callback(value); }

En ese ejemplo, la callback es una referencia a su función. No tiene ningún contexto. Como ya ha notado, puede solucionarlo vinculando la función a un contexto antes de pasarla a ese momento.


this es siempre el objeto al que se llama el método. Sin embargo, al pasar el método a then() , ¡no lo está llamando! El método se almacenará en algún lugar y se llamará desde allí más tarde. Si desea preservar this , deberá hacerlo así:

.then(() => this.method2())

o si tiene que hacerlo de la forma anterior a ES6, debe preservar this antes de:

var that = this; // ... .then(function() { that.method2() })