23

原文来源:http: //twitter.com/tobeytailor/status/8998006366

(x=[].reverse)() === window // true

我注意到这种行为会影响所有本机类型。这里到底发生了什么?

4

1 回答 1

41

这与this绑定在 JavaScript 中的奇怪方式有关。

[].reverse

reverse是空列表上的方法。如果您调用它,请通过以下方式之一:

[].reverse();
[]['reverse']();
([].reverse)();

然后它在this绑定到列表实例的情况下执行[]。但是如果你分离它:

x= [].reverse;
x();

它在没有this-binding 的情况下执行,因此this在函数中指向全局 ( window) 对象,这是 JavaScript 最糟糕、最具误导性的设计错误之一。

(x=[].reverse)()

也在做分离。赋值运算符返回它传递的同一个函数对象,所以看起来它什么也没做,但它的副作用是打破了导致 JavaScript 绑定的有限特殊情况this

所以你说:

Array.prototype.reverse.call(window)

reverse与许多其他Array.prototype方法一样,由 ECMAScript 定义,用于处理任何本机类似序列的对象。它使用数字字符串键(最多object.length)反转项目并返回对象。因此,它将返回为具有length属性的任何类型传入的对象。

window有一个长度属性,它对应于,因此使用指向window.frames.length调用此方法将起作用并返回. 理论上它可能仍然会失败,因为:thiswindowwindow

  1. window允许作为“宿主对象”而不是“本地对象”;在这种情况下,您可以传递给其他原型的方法的保证不一定适用;和
  2. 如果窗口实际上有框架/iframe,它会尝试颠倒它们的顺序,这不起作用,因为框架集合是只读的。

但是,在当前的浏览器中,前一种情况确实有效,而后一种情况会静默失败而不会出现错误,因此您仍然会得到===window行为而不是异常。

于 2010-02-14T14:28:07.973 回答