Javascript node.js中的全局作用域与浏览器中的全局作用域有何不同(有具体示例)?

Javascript node.js中的全局作用域与浏览器中的全局作用域有何不同(有具体示例)?,javascript,node.js,Javascript,Node.js,我遇到了凯尔·辛普森(Kyle Simpson)关于这个和对象原型的优秀的“你不知道JS”书的问题 如果您想阅读关于发生了什么的完整上下文,本书的文本将包含在GitHub链接中 下面是有问题的代码: if (!Function.prototype.softBind) { Function.prototype.softBind = function(obj) { var fn = this, curried = [].slice.call( arguments, 1 )

我遇到了凯尔·辛普森(Kyle Simpson)关于这个和对象原型的优秀的“你不知道JS”书的问题

如果您想阅读关于发生了什么的完整上下文,本书的文本将包含在GitHub链接中

下面是有问题的代码:

if (!Function.prototype.softBind) {
  Function.prototype.softBind = function(obj) {
    var fn = this,
      curried = [].slice.call( arguments, 1 ),
      bound = function bound() {
        if (this === global) {console.log('this is global')}
        console.log(this);
        return fn.apply(
          (!this ||
          (typeof window !== "undefined" &&
          this === window) ||
          (typeof global !== "undefined" &&
          this === global)
          ) ? obj : this,
          curried.concat.apply( curried, arguments )
        );
      };
    bound.prototype = Object.create( fn.prototype );
    return bound;
  };
}

function foo() {
  console.log("name: " + this.name);
}

var obj = { name: 'obj'};
var obj2 = { name: 'obj2'};
var obj3 = { name: 'obj3'};

var fooOBJ = foo.softBind(obj);

fooOBJ(); // name: obj

obj2.foo = foo.softBind(obj);
obj2.foo(); // name: obj2
fooOBJ.call(obj3); // name: obj3

setTimeout(obj2.foo, 10); // name: obj (only in browser, name: undefined if in node)
出于这个问题的目的,我只对最后一行代码的输出感兴趣,正如注释所示,在浏览器中打印“name:obj”,但在节点中打印“name:undefined”


有人能解释一下这种差异的原因吗?是否可以对softBind函数进行更改,从而使代码在两种环境中都能正常工作

如您在
绑定
中记录
this
的值所见,当函数被称为
设置超时
回调时,
被设置为一个特殊的超时对象:

{ _idleTimeout: 10,
  _idlePrev: null,
  _idleNext: null,
  _idleStart: 1417462313179,
  _monotonicStartTime: 36214497,
  _onTimeout: [Function: bound],
  _repeat: false }
也就是说,与浏览器中的
setTimeout
不同,它不引用全局对象。这就是为什么

(typeof global !== "undefined" && this === global)

未实现,并且
foo
设置为超时对象,而不是
obj

如您在
绑定
中记录
this
的值所见,当函数被称为
设置超时
回调时,
被设置为一个特殊的超时对象:

{ _idleTimeout: 10,
  _idlePrev: null,
  _idleNext: null,
  _idleStart: 1417462313179,
  _monotonicStartTime: 36214497,
  _onTimeout: [Function: bound],
  _repeat: false }
也就是说,与浏览器中的
setTimeout
不同,它不引用全局对象。这就是为什么

(typeof global !== "undefined" && this === global)

未实现,并且
foo
设置为超时对象,而不是
obj

运行节点v0.10.26运行节点v0.10.26正常,但节点为什么要这样做?谢谢你的回答,但我只是想知道为什么这种行为与Chrome或Firefox中的行为不同。我不能给你一个明确的答案,但请记住,
setTimeout
不是ECMAScript规范的一部分。它是由浏览器提供的,只是最近才正式成为HTML5的一部分。但是,本规范并未规定此
应参考的内容。实际上,
this
引用全局对象的事实被视为不利因素,这就是为什么在严格模式下禁用此行为的原因。这不是我所希望的启示,而是提供了澄清。非常感谢你!澄清:HTML规范实际上规定了由
setTimeout(…)
调用的函数中的
this
应该始终是全局的。所有浏览器都会/应该遵守这一点。但是,节点不受HTML规范的约束,因此允许并且确实有自己的
setTimeout(..)
实现,其工作方式不同,如上所述:/好的,但是node为什么要这样做呢?谢谢你的回答,但我只是想知道为什么这种行为与Chrome或Firefox中的行为不同。我不能给你一个明确的答案,但请记住,
setTimeout
不是ECMAScript规范的一部分。它是由浏览器提供的,只是最近才正式成为HTML5的一部分。但是,本规范并未规定此
应参考的内容。实际上,
this
引用全局对象的事实被视为不利因素,这就是为什么在严格模式下禁用此行为的原因。这不是我所希望的启示,而是提供了澄清。非常感谢你!澄清:HTML规范实际上规定了由
setTimeout(…)
调用的函数中的
this
应该始终是全局的。所有浏览器都会/应该遵守这一点。但是,节点不受HTML规范的约束,因此允许并且确实有自己的
setTimeout(..)
实现,其工作方式不同,如上所述:/