【问题标题】:Can somebody explain this Javascript method?有人可以解释这个 Javascript 方法吗?
【发布时间】:2011-01-16 17:00:52
【问题描述】:

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

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

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

【问题讨论】:

  • [].reverse.call(y) === y 对于所有标量 y
  • 我注意到这种行为...什么行为?
  • 这会在更现代的引擎中引发错误,因为Array.prototype.reverse 设置为严格模式,其中未定义的this 值实际上是undefined 而不再是globalThis(即window在浏览器中,global 在 Node.js 中)。

标签: javascript string window reverse


【解决方案1】:

这与 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,因此使用指向windowthis 调用此方法将起作用并返回window。理论上它可能仍然会失败,因为:

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

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

【讨论】:

  • 你知道为什么有人会编写代码吗?我的意思是,我当然理解为什么会发生这种效果,但我为什么要把它放在我的代码中呢?它实现了什么?
  • 绝对没有。它只是展示了 JavaScript 的许多意想不到的行为之一。如果我在真实代码中找到了这个,我会担心的!
  • 这样做的一个可能原因是检查是否有其他脚本与窗口对象混淆(window = open('http://google.com/') 就足够了)。 var window = (x=[].reverse)(); 可以在本地恢复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多