Settimeout,bind和this

时间:2016-08-03 07:18:27

标签: javascript this settimeout

我在这里复制了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总是绑定到全局对象。我知道 var self var 内部绽放功能。

该行中有两个thisthis指的是什么以及如何工作完全令人困惑。

如何运作?

3 个答案:

答案 0 :(得分:4)

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中,我们将this的{​​{1}}绑定到声明函数,通过该函数我们可以访问LateBloomer的对象{{1} }。

JavaScript中的

LateBloomer起初非常难以理解。

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

答案 1 :(得分:4)

首先阅读this link。关于this如何运作的非常好的解释。

.bind(this, args)只是帮助您在函数中传递this上下文(因为在其中,默认情况下this中的undefinedwindow或引用到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

这使您可以不考虑names(cluster)

答案 2 :(得分:0)

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);}