简体   繁体   English

设置超时,绑定和这个

[英]Settimeout, bind and this

Here I have copied code snippet from MDN : https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind这里我从 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

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

I understand how this works and this inside settimeout is always bound to global object.I know there can be var self or var that inside bloom function.我了解this是如何工作的,并且 settimeout 内部的this始终绑定到全局对象。我知道bloom函数内部可以有var selfvar

There are two this in that line but which this refers to what and how that works is totally confusing.该行中有两个this ,但是this指的是什么以及如何工作,这完全令人困惑。

How works?如何运作?

First of all read this article , which offers a very nice explanation about how this works.首先,阅读这篇文章,它提供了有关如何一个很好的解释this作品。

.bind(this, args) just helps you to pass your this context inside your function (because inside it in your example by default this is undefined or refers to window ). .bind(this, args)只是帮助您将this上下文传递到您的函数中(因为在您的示例中,默认情况下thisundefined或指的是window )。

Also bind is a nice alternative to this:另外bind是一个很好的替代方案:

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

And as the last point in es6 you can do it in this way:作为es6的最后一点,你可以这样做:

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

instead of而不是

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

this allow you to not think about this .这让你不用考虑this

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

The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called. bind() 方法创建一个新函数,在调用该函数时,将其 this 关键字设置为提供的值,并在调用新函数时在任何提供的参数之前提供给定的参数序列。

By using .bind(this) we are passing this to the function declare通过使用.bind(this)我们将this传递给函数declare

See this snippet.看到这个片段。

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

In the function undefinedbloom we are just calling the declare function.undefinedbloom函数中,我们只是调用了声明函数。 So the object will be the window object.所以对象将是window对象。 It doesn't have property petalCount so its undefined.它没有属性petalCount所以它未定义。

In the function bloom we are binding the this of LateBloomer to the declare function by which we will have access to the LateBloomer 's object petalCount .在函数bloom我们将LateBloomerthis LateBloomer到declare 函数,通过它我们可以访问LateBloomer的对象petalCount

this in JavaScript is a very difficult to fathom at first. JavaScript 中的this一开始很难理解。

MDN Link: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/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);}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM