以下代码在 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]
为什么没有异常(exception)?我在 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.1th Edition,但我找不到这样的部分。)
最佳答案
ECMA 262 5.1表示 Array.prototype.push
的以下内容:
15.4.4.7
Array.prototype.push ( [ item1 [ , item2 [ , … ] ] ] )
....
- Let
O
be the result of callingToObject
passing the this value as the argument.- Let
lenVal
be the result of calling the[[Get]]
internal method ofO
with argument "length
".- Let
n
beToUint32(lenVal)
.- Let
items
be an internal List whose elements are, in left to right order, the arguments that were passed to this function invocation.- Repeat, while items is not empty
- Remove the first element from items and let
E
be the value of the element.- Call the
[[Put]]
internal method ofO
with argumentsToString(n)
,E
, andtrue
.- Increase
n
by 1.- Call the
[[Put]]
internal method of O with arguments "length", n, and true.- Return n.
请注意 [[Put]]
的参数 3 如何为 true
。现在,[[Put]]
定义为
8.12.5
[[Put]] ( P, V, Throw )
When the
[[Put]]
internal method ofO
is called with propertyP
, valueV
, and Boolean flagThrow
, the following steps are taken:
- If the result of calling the
[[CanPut]]
internal method ofO
with argumentP
isfalse
, then
- If
Throw
istrue
, then throw aTypeError
exception.- Else return.
...
[[CanPut]]
然后返回 false
等,如果 [[Extensible]]
on 数组O
为 false
。
因此,您的 Chrome 违反了 ECMA 262 5.1 规范。
更新:
Chrome 开发人员正在讨论让 push
、pop
在严格模式下运行;然而,区别不仅仅是“严格”与“非严格”,因为 push
和 pop
的行为在 ECMA 262 5.1 规范中有非常明确的规定。
关于javascript - 在 Chrome 中推送和弹出卡住数组不会抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18200797/