与浏览器(具体示例)相比,node.js中的全局范围有何不同?

时间:2014-12-01 19:21:13

标签: javascript node.js

我遇到过Kyle Simpson的优秀问题"你不了解JS"关于这个& amp;对象原型。

OReilly link

Official GitHub link

本书的内容包含在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)

出于这个问题的目的,我只对最后一行代码的输出感兴趣,因为评论显示print' name:obj'在浏览器中,但是名称:undefined'在节点中。

有人可以解释这种差异的方式和原因吗?是否可以对softBind函数进行更改,这将导致代码在两种环境中的工作方式相同?

1 个答案:

答案 0 :(得分:4)

正如您在this内记录bound的值所看到的那样,当函数被调用为setTimeout回调时,this被设置为一个特殊的超时对象:

{ _idleTimeout: 10,
  _idlePrev: null,
  _idleNext: null,
  _idleStart: 1417462313179,
  _monotonicStartTime: 36214497,
  _onTimeout: [Function: bound],
  _repeat: false }

即。与浏览器中的setTimeout不同,引用全局对象。这就是为什么

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

未得到满足,this的{​​{1}}设置为超时对象,而不是foo