我遇到过Kyle Simpson的优秀问题"你不了解JS"关于这个& amp;对象原型。
本书的内容包含在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函数进行更改,这将导致代码在两种环境中的工作方式相同?
答案 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
。