javascript - 在 Chrome 中推送和弹出卡住数组不会抛出异常

标签 javascript ecmascript-5 ecma262

以下代码在 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有区别,然后我意识到这可能是因为poppush方法的严格模式。综上所述,在 Firefox(SpiderMonkey)中,poppush 方法是在严格模式下定义的,但在 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 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.

请注意 [[Put]] 的参数 3 如何为 true。现在,[[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 等,如果 [[Extensible]] on 数组Ofalse

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

更新:

Chrome 开发人员正在讨论让 pushpop 在严格模式下运行;然而,区别不仅仅是“严格”与“非严格”,因为 pushpop 的行为在 ECMA 262 5.1 规范中有非常明确的规定。

关于javascript - 在 Chrome 中推送和弹出卡住数组不会抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18200797/

相关文章:

javascript - 使用切换开关而不是按钮或链接制作 bootstrap 4.x nav pills make it switch

javascript - 我的正则表达式的某些部分不起作用

javascript - 没有严格模式的 JSON.parse

javascript - ECMAScript 规范中是否存在与 Unicode 代码点相关的错误?

javascript - 为什么 BigInt 要求从 Number 进行显式转换?

javascript - 找不到模块 : Error: Can't resolve 'X\node_modules\ng-zorro-antd\src\ng-zorro-antd.less'

typescript - 在 typescript 中创建动态类实例

javascript - Object.keys 不会将方法名称打印为属性

JavaScript 函数指针作用域

javascript - 如何判断鼠标滚动方向是向上还是向下?