我在这里复制了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 内部绽放功能。
该行中有两个this
但this
指的是什么以及如何工作完全令人困惑。
如何运作?
答案 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} }。
LateBloomer
起初非常难以理解。
MDN链接:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/this
答案 1 :(得分:4)
首先阅读this link。关于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
这使您可以不考虑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);}