以下代码似乎未在Chrome下按预期运行,并且在Firefox中运行方式不同。
(function () {
'use strict';
var
arr = Object.freeze([1, 2, 3]);
try {
arr.push(4);
} catch (e) {
console.log(e);
}
try {
console.log(arr.pop());
}catch (e) {
console.log(e);
}
console.log(arr);
})();
我预计输出会是:
Error : (for `arr.push(4)`)
Error : (for `arr.pop()`)
[1, 2, 3]
但是在Chrome 29.0.1547.49(官方版本216092)beta-m上运行此代码时,我收到以下输出:
3
[1, 2, 3]
为什么没有例外?我在Firefox Nightly 26.0a1(2013-08-12)上运行了这段代码,结果是
TypeError: arr.push(...) is not extensible
TypeError: property arr.pop(...) is non-configurable and can't be deleted
[1, 2, 3]
正如我所料。
我想到了为什么Chrome和Firefox之间的区别,然后我意识到这可能是因为pop
和push
方法的严格模式。总而言之,在Firefox(SpiderMonkey)中pop
和push
方法是在严格模式下定义的,但在Chrome(V8)中,这些方法没有在严格模式下定义。
我不知道实际的规格是什么。 (我读了一些ECMA-262第5.1版,但我找不到这样的部分。)
答案 0 :(得分:6)
ECMA 262 5.1说明了以下Array.prototype.push
:
15.4.4.7
Array.prototype.push ( [ item1 [ , item2 [ , … ] ] ] )
...
- 让
O
成为调用ToObject
传递此值作为参数的结果。- 让
lenVal
成为使用参数“[[Get]]
”调用O
length
内部方法的结果。- 让
n
成为ToUint32(lenVal)
。- 让
items
成为一个内部List,其元素按从左到右的顺序排列为传递给此函数调用的参数。- 重复,而项目不为空
- 从项中删除第一个元素,并让
E
为元素的值。- 使用参数
[[Put]]
,O
和ToString(n)
调用E
true
内部方法。- 将
n
增加1。- 使用参数“length”,n和true调用O的
[[Put]]
内部方法。- 返回n。
注意[[Put]]
的参数3是true
。现在,[[Put]]
被定义为
8.12.5
[[Put]] ( P, V, Throw )
使用属性
[[Put]]
调用O
P
的内部方法时, 值V
和布尔标志Throw
,执行以下步骤:
- 如果调用带有参数
[[CanPut]]
的{{1}}的{{1}}内部方法的结果是O
,那么
- 如果
P
为false
,则抛出Throw
例外。- 别的回归。
...
true
然后返回TypeError
等数据,如果[[CanPut]]
上的false
为[[Extensible]]
,则返回数组。
因此,您的Chrome 违反了ECMA 262 5.1规范。
<强>更新强>
Chrome开发人员正在讨论如何在严格模式下运行O
,false
;然而,差异不仅仅是“严格”与“非严格”,因为push
和pop
的行为在ECMA 262 5.1规范中具体指定。