“setTimeout”将“this”绑定到什么
what does `setTimeout` bind `this` to?
我正试图创建一个示例来演示为什么成语var that = this
是必要的(例如,如本文所述)。
因此,我从一个错误代码的例子开始,该错误代码将无法正确绑定this
。然而,我写的代码(在另一个方向上)给了我一些意想不到的结果:
message = "message in global scope";
// the below erroneous code aims to demonstrate why we need
// the "var that = this" idiom to capture the "this" lexical scope
var createLoggingFunctionWrongWay = function () {
return function () {
console.log(this.message);
};
};
// the below *does* print "message in global scope"
// i.e. fails in the way I expected
createLoggingFunctionWrongWay.call({message:"message"})();
// I was expecting the below to also print "message in global scope" as
// well, yet it prints "undefined"
setTimeout(createLoggingFunctionWrongWay.call({
message: "message"
}), 1000);
当在nodejs
下运行时,我得到:
$ nodejs foo.js
message in global scope
undefined
我的问题是,为什么第二个调用(使用setTimeout
)不会以同样的方式失败,并将this
解释为指向Node.js
中的global
对象(message
变量所在的位置)?
更新当我在匿名函数中插入console.log(this)
时,在第一次调用中,我得到全局上下文对象(message
所在的位置),而在第二次调用中(通过setTimeout
),我得到以下对象:
{ _idleTimeout: 1000,
_idlePrev: null,
_idleNext: null,
_idleStart: 1446483586705,
_onTimeout: [Function],
_repeat: false
}
在Node.js中,setTimeout
的回调是用绑定为上下文(this
)对象的Timeout
对象调用的,并且它们没有定义message
。这就是为什么第二种方法打印CCD_ 16。您可以在此处看到相应的代码段。
var timer = new Timeout(after);
var length = arguments.length;
var ontimeout = callback;
switch (length) {
// fast cases
case 0:
case 1:
case 2:
break;
case 3:
ontimeout = callback.bind(timer, arguments[2]);
break;
case 4:
ontimeout = callback.bind(timer, arguments[2], arguments[3]);
break;
case 5:
ontimeout =
callback.bind(timer, arguments[2], arguments[3], arguments[4]);
break;
// slow case
default:
var args = new Array(length - 2);
for (var i = 2; i < length; i++)
args[i - 2] = arguments[i];
ontimeout = callback.apply.bind(callback, timer, args);
您可以通过bind
方法将作用域传播到返回的函数:
message = "message in global scope";
var createLoggingFunctionWrongWay = function () {
return (function () {
console.log(this.message);
}).bind(this);
};
setTimeout(createLoggingFunctionWrongWay.call({ message: "message" }), 1000);
否则,它在其范围内工作,这实际上是通过忽略注入到最外层函数的函数而导致全局函数。
一个没有注入作用域的简单函数调用(也就是说,既不使用call
,也不使用apply
或bind
等等)将全局上下文作为其默认上下文。这主要是因为函数调用必须有上下文,但在这种情况下,没有特定的上下文绑定到该函数,因此它默认为全局上下文。
请注意,我们谈论的是不属于原型的函数。
相关文章:
- 当绑定到AngularJS中的函数时,会在后台发生什么
- 绑定返回的结果和使用function()的结果之间有什么区别
- 在表单提交将DOM的一部分替换为分部之后,我应该将ajax成功绑定到什么来使我的javascript工作
- 为D3.js动画编写绑定的正确方法是什么
- setTimeout vs. 事件绑定/取消绑定;什么更有效
- 在 aurelia 中使用 repeat.for 绑定自定义元素的正确方法是什么
- 那么承诺和AngularJS中的绑定有什么区别
- 将所有函数绑定到窗口对象有什么用
- 绑定函数的返回语句中参数的推理是什么
- 在后台发生什么,以防止调用更改此对象的绑定方法
- 在 Angular 1.5 中使用“单向绑定”(<)有什么意义
- on() 和 off(),on() 立即触发,但我希望它像绑定或生活一样“行动”,这里有什么问题
- 如果函数的 toString() 以“绑定:”开头,这意味着什么?
- 在 JavaScript 中引入局部变量的所有方法是什么,它们绑定了什么?
- 什么是 ractivejs 中焦点的反向绑定
- 在Ember.js视图中刷新jQuery绑定的正确方法是什么
- D3这两种数据绑定方式有什么区别
- angularjs中支持单向绑定的指令是什么
- 如果我将一个JavaScript事件绑定到一个元素,然后删除该元素,事件会发生什么
- 什么's将别名绑定到本地方法的优点