什么`setTimeout`绑定这个`?

我试图创build一个例子,说明为什么成语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" // ie 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.jsmessagevariables所在的地方)的global对象?

更新当我在匿名函数中插入一个console.log(this) ,在第一次调用时我得到了全局上下文对象(其中有message所在),而在第二次调用时(通过setTimeout ),我得到以下对象:

 { _idleTimeout: 1000, _idlePrev: null, _idleNext: null, _idleStart: 1446483586705, _onTimeout: [Function], _repeat: false } 

在Node.js中, setTimeout的callback函数被作为上下文( this )对象绑定的Timeout对象调用,并且它们没有在其中定义的message 。 这就是为什么第二个方法打印undefined 。 你可以在这里看到相应的代码段。

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

否则,它在其范围内工作,实际上是通过忽视注入到最外层function的那个而导致全球性的。

一个简单的函数调用,没有注入的作用域(也就是说,你既没有使用call ,也没有applybind等等),全局上下文是默认的。 这主要是因为函数调用必须有一个上下文,但在这种情况下,没有特定的上下文绑定到该函数,所以它默认为全局的。

请注意,我们正在谈论的function不是原型的一部分。