编程语言
首页 > 编程语言> > javascript – 在Chrome中的冻结数组上推送并弹出不会引发异常

javascript – 在Chrome中的冻结数组上推送并弹出不会引发异常

作者:互联网

以下代码似乎没有在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版,但我找不到这样的部分.)

解决方法:

ECMA 262 5.1说下面的Array.prototype.push:

15.4.4.7 Array.prototype.push ( [ item1 [ , item2 [ , … ] ] ] )

….

  • Let O be the result of calling ToObject passing the this value as the argument.
  • Let lenVal be the result of calling the [[Get]] internal method of O with argument “length“.
  • Let n be ToUint32(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 of O with arguments ToString(n), E, and true.
    • Increase n by 1.
  • Call the [[Put]] internal method of O with arguments “length”, n, and true.
  • Return n.

注意参数3到[[Put]]是如何成立的.现在,[[Put]]被定义为

8.12.5 [[Put]] ( P, V, Throw )

When the [[Put]] internal method of O is called with property P,
value V, and Boolean flag Throw, the following steps are taken:

  • If the result of calling the [[CanPut]] internal method of O with argument P is false, then
    • If Throw is true, then throw a TypeError exception.
    • Else return.

[[CanPut]]然后返回false,在数组的情况下,如果O上的[[Extensible]]为false.

因此,您的Chrome违反了ECMA 262 5.1规范.

更新:

Chrome开发人员正在谈论在严格模式下进行推送,弹出运行;然而,差异不仅仅是“严格”与“非严格”,因为推送和弹出的行为在ECMA 262 5.1规范中非常具体地指定.

标签:javascript,ecmascript-5,ecma262
来源: https://codeday.me/bug/20190529/1177169.html