结算,绑定和这个



这里我已经从MDN复制了代码片段:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind

function LateBloomer() {
  this.petalCount = Math.ceil(Math.random() * 12) + 1;
}
// Declare bloom after a delay of 1 second
LateBloomer.prototype.bloom = function() {
  window.setTimeout(this.declare.bind(this), 1000);
};
LateBloomer.prototype.declare = function() {
  console.log('I am a beautiful flower with ' +
    this.petalCount + ' petals!');
};
var flower = new LateBloomer();
flower.bloom();  
// after 1 second, triggers the 'declare' method

最令人困惑的部分是:window.setTimeout(this.declare.bind(this), 1000);

我理解this是如何工作的,并且settimeout内部的this总是绑定到全局对象。我知道bloom函数内部可能有var selfvarthat

这行有两个this,但哪个this指的是什么以及如何工作,这完全令人困惑。

如何工作?

首先阅读本文,它提供了关于this如何工作的非常好的解释。

.bind(this, args)只是帮助您在函数中传递this上下文(因为在您的示例中,this默认为undefined或指window)。

此外,bind是一个很好的替代方案:

// Declare bloom after a delay of 1 second
LateBloomer.prototype.bloom = function() {
  var self = this;
  window.setTimeout(self.declare, 1000);
};

作为es6中的最后一点,你可以这样做:

window.setTimeout(() => {
  //do some stuff
}, 1000);

而不是

window.setTimeout(function () {
  //do some stuff
}.bind(this), 1000);

这允许您不用考虑this

MSDN将Function.prototype.bind()定义为,

bind()方法创建一个新函数,当调用该函数时该关键字设置为提供的值,具有给定的在调用新函数时提供的任何参数之前的参数。

通过使用.bind(this),我们将this传递给函数declare

请参阅此片段。

function LateBloomer() {
  console.log(this.constructor);
  this.petalCount = Math.ceil(Math.random() * 12) + 1;
}
// Declare bloom after a delay of 1 second
LateBloomer.prototype.bloom = function() {
  window.setTimeout(this.declare.bind(this), 1000);
};
LateBloomer.prototype.undefinedbloom = function() {
  window.setTimeout(this.declare, 1000);
};
LateBloomer.prototype.declare = function() {
  console.log(this.constructor);
  console.log('I am a beautiful flower with ' +
this.petalCount + ' petals!');
};
var flower = new LateBloomer();
flower.bloom();
flower.undefinedbloom();

在函数undefinedbloom中,我们只是在调用declare函数。因此,对象将是window对象。它没有属性petalCount,因此未定义。

在函数bloom中,我们将LateBloomerthis绑定到声明函数,通过该函数我们可以访问LateBloomer的对象petalCount

JavaScript中的this一开始很难理解。

MDN链接:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/this

function LateBloomer() {
  this.name = 'triven'; //simplified property
}
// Some thoughts we discuss main requirement.
LateBloomer.prototype.bloom = function() {
  window.setTimeout(function() {console.log(this);}, 1000); //Logs window: We all know that keyword this INSIDE CALLBACK 
                                                            //function refers to Window [Comment 1]
  //window.setTimeout(console.log(this), 1000); /Attentions: Here it is very easy to MISUNDERSTAND 
                                                //that keyword this is inside setTimeout and it should refer to window. 
                                                //Please note that here keyword this is not INSIDE CALLBACK function so here 
                                                //keyword this will refer to object on which its wrapper function is 
                                                //executed(in our case flower). [Comment 2]
};
//The requirement: We need to call .bloom and it should log name after 1 second. 
LateBloomer.prototype.bloom = function() {
    //here keyword this refers to object
   //window.setTimeout(function() {console.log(this);}, 1000); //But inside callback keyword this refers to window.
};
//We need some way to access object inside call back function so that its name can be accessed after 1 sec.
//step 1; Taking out anonymous function and adding it as a prototype property
LateBloomer.prototype.bloom = function() {
  //window.setTimeout(this.callback, 1000); //Note: Keyword this is not inside callback so 
                                            //it is referring to object (not window). We can access newly 
                                            //defined function on the object.  Also keyword this placed inside callback 
                                            //function(below) will still refer to window. 
};
LateBloomer.prototype.callback = function() {console.log(this.name);} 
//step 2; bringing .bind into picture.
    //Definition of .bind as per MDN : The bind() method creates a new function 
    //that, when called, has its this keyword set to the provided value
LateBloomer.prototype.bloom = function() {
  window.setTimeout(this.callback.bind(this), 1000); // Okay now we are now invoking .callback method on the object and 
                                                    //passing the same object to bind. 
                                                    // The keyword this inside newly return function (as a result of bind) will now refer to object
                                                    // we passed as argument to bind and we should not be able to access name property of our object.
                                                    // Note : Here both this keywords refers to same object ie on which which are calling .bloom.
                                                    //Note : we are no longer using passing callback function defined below. Instead we are now passing 
                                                    // and exact copy of it but configuring it in such a way that keyword this start refering to object we passed.
};
LateBloomer.prototype.callback = function() {console.log(this.name);}

最新更新