窗口/全局和数字属性上的Array.push.call

时间:2013-12-05 10:01:29

标签: javascript node.js google-chrome firefox safari

当我运行这行代码时:

> var new_arr_length = Array.prototype.push.call(this, null);

我得到了非常奇怪的结果。

MDN documentation表示push()应该返回应用了推送的数组的长度:

  

返回

     

方法所针对的对象的新长度属性   调用。

但这就是你得到的:

> new_arr_length
    Chrome中的
  • 您获得了17,因为最初,此0的{​​{1}}个属性15等于window

  • 在Node.js中
  • 得到"DOMException"。此处1将是this对象。

  • 在Safari中
  • 您获得global,因为最初,此属性301)等于window

    < / LI>
  • 并且在Firefox中出现Window错误

这导致我提出以下问题:

  1. 为什么Chrome TypeError: setting a property that has only a getter来自"DOMException"this[0]

  2. 为什么Safari this[15]适用于Windowthis[0]

  3. 为什么Firefox是唯一一个this[1]和其他浏览器在TypeError上快乐执行Array方法的人?

  4. 当然,这个特定的代码行是丑陋的,仅仅是一个实验而不是实际项目中使用的东西。

    提前谢谢!

1 个答案:

答案 0 :(得分:1)

一些事情:

1)通常,n为整数的window[n]将是页面上第n个子帧的窗口。这就是Givi在没有框架的页面上的评论中看到的内容:长度为0,没有索引属性以及您在Safari中看到的内容。

2)在Chrome“新标签页”上,有一堆<iframe>标签。其中17个,在这里。快速查看它,window[0]window[16]实际上是该页面上那些子帧的Window对象。我不知道为什么你会看到DOMException。

3)Array方法(包括Array.prototype.push)大多是通用的。也就是说,它们的定义使得它们可以处理任何对象,而不仅仅是在数组上。如果您查看http://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.prototype.push处的规范,您会看到所有push如果是这个对象,则获取.length,然后将n设置为该长度,然后每个传递的参数设置thisObj[n] = argument(排序;参见下面的第4项)并将n增加1.然后在最后设置this.length = n。这些都是通常对任何对象都有意义的操作。

4)如果仔细查看实际定义push的方式,实际设置属性n的作用是Put(O, ToString(n), E, true)。如果查看http://people.mozilla.org/~jorendorff/es6-draft.html#sec-put-o-p-v-throw,您将看到最后一个参数是在[[Set]]调用失败时是否抛出异常。现在,如果你真的尝试在Firefox中设置Window上的索引属性,那么这些集实际上是失败的。在严格模式下,您会获得例外;在非严格模式下,这些集合是无声的无操作。这实际上是http://heycam.github.io/webidl/#defineownproperty处WebIDL规范所要求的行为(特别是步骤1子步骤4,如果索引没有子窗口,步骤1子步骤5,如果索引确实有子窗口,因为Window既没有索引属性setter也没有索引属性创建者。据推测,其他浏览器还没有实现这部分规范。我应该注意到Firefox也没有很好地实现它。正如你所注意到的,它常常在Put(O, "length", n, true)上抛出这种情况,但当前的夜莺不会因为length被修复为可替换的属性,所以它实际上可以设置。但是一旦https://bugzilla.mozilla.org/show_bug.cgi?id=828137被修复,它将再次抛出。