当我运行这行代码时:
> var new_arr_length = Array.prototype.push.call(this, null);
我得到了非常奇怪的结果。
MDN documentation表示push()
应该返回应用了推送的数组的长度:
返回
方法所针对的对象的新长度属性 调用。
但这就是你得到的:
> new_arr_length
您获得了17
,因为最初,此0
的{{1}}个属性15
等于window
。
得到"DOMException"
。此处1
将是this
对象。
您获得global
,因为最初,此属性3
和0
(1
)等于window
并且在Firefox中出现Window
错误
这导致我提出以下问题:
为什么Chrome TypeError: setting a property that has only a getter
来自"DOMException"
到this[0]
?
为什么Safari this[15]
适用于Window
和this[0]
?
为什么Firefox是唯一一个this[1]
和其他浏览器在TypeError
上快乐执行Array
方法的人?
当然,这个特定的代码行是丑陋的,仅仅是一个实验而不是实际项目中使用的东西。
提前谢谢!
答案 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被修复,它将再次抛出。