注意:此问题中的代码是在Chrome控制台中运行的。
我在做JS-puzzler问题21时遇到了这个问题(好吧......虽然没有给出排序)。问题是关于结果:
var x = [].reverse; x();
,答案是window
。正如答案所述:
[] .reverse将返回此值,并且在没有显式接收器对象的情况下调用时,它将默认为默认的此AKA窗口。
基于这种理解,我写了一些代码来测试:
function Bar(){
var x = [].reverse;
console.log(x());
}
new Bar();
猜猜是什么..这段代码引发了错误:
TypeError:在null或undefined
上调用Array.prototype.reverse
我想问为什么new Bar
中调用的x()没有显示this
对象,而是提出异常?
答案 0 :(得分:5)
当您在x()
中调用函数时,this
指针将设置为window
或undefined
(在严格模式下)。调用函数的方法是确定this
的值。
让您控制this
的值的调用方法是:
x.call(xxx)
x.apply(xxx)
foo.x()
呼叫为:
x()
会将this
设置为普通JS模式下的window
或严格模式下的undefined
的默认值。
您可能想要了解的另一件事是,一旦您这样做:
var x = [].reverse;
然后,x
仅保留对reverse()
函数的引用。与您最初使用的[]
完全没有关联。因此,当您调用x()
时,您只是调用没有对象关联的reverse()
函数,因此this
被设置为普通JS中的window
的默认值模式或JS严格模式下的undefined
。
答案 1 :(得分:1)
这是因为您在没有执行范围的情况下获得了函数引用。 reverse
函数在其源代码中引用this
。如果你正确地调用了一个函数:
var obj = {
run: function() { console.log(this) }
};
obj.run(); // this will be obj, as expected
但如果你这样称呼它:
var broken = obj.run;
broken(); // this will be the global object
这就是javascript执行在范围方面的工作方式。在对象上调用带点符号的函数将使this
成为它所在的对象。
如果您使用的是现代浏览器,则可以bind
this
的价值{/ 1}}:
var arr = [1,2,3];
var boundReverse = arr.reverse.bind( arr );
boundReverse() // [3, 2, 1]
答案 2 :(得分:0)
原始问题是关于以下代码的输出。
var x = [].reverse;
x();
但上面代码段的输出是
Uncaught TypeError: Array.prototype.reverse called on null or undefined
实际上,等效的调用给出了同样的错误:
Array.prototype.reverse.call();
所以,关于JavaScript Puzzler的问题的答案是不正确的。虽然Array.prototype.reverse
返回this
,但代码段仍然会因缺少关联对象而引发错误。
如果测试人员通过var
了解了函数定义,则可以使用此问题进行测试,其中var
仅保存方法并删除关联对象。
解决方案:(通过调用绑定关联对象)
// An associated object can be bound as below.
var x = [].reverse;
x.bind([1,2,3])();
// output : [3,2,1]
// equivalent to
Array.prototype.reverse.call([1,2,3]);