4

次のコードは、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 の違いについて考えてみたところ、厳密なモードpoppushメソッドが原因である可能性があることに気付きました。要約すると、Firefox (SpiderMonkey) ではpopメソッドpushは厳密モードで定義されていますが、Chrome (V8) ではこれらのメソッドは厳密モードで定義されていません。

実際の仕様はわかりません。(ECMA-262 5.1th Edition をいくつか読みましたが、そのようなセクションが見つかりません。)

4

1 に答える 1

6

ECMA 262 5.1は、次のように述べていますArray.prototype.push

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

....

  • this値を引数として渡してO呼び出した結果とする。ToObject
  • 引数" " で の内部メソッドをlenVal呼び出した結果とします。[[Get]]Olength
  • しましょnToUint32(lenVal)
  • 要素が左から右の順序で、この関数items呼び出しに渡された引数である内部 List とします。
  • アイテムが空でない間、繰り返します
    • アイテムから最初の要素を削除し、E要素の値にします。
    • 引数、、およびを使用して の[[Put]]内部メソッドを呼び出します。OToString(n)Etrue
    • 1 ずつ増やしnます。
  • [[Put]]引数 "length"、n、および true を指定して Oの内部メソッドを呼び出します。
  • n を返します。

引数 3 to[[Put]]が であることに注意してくださいtrue[[Put]]は、次のように定義されます。

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

[[Put]]内部メソッドがOproperty P、 value V、および Boolean flagThrowで呼び出されると、次の手順が実行されます。

  • 引数を指定して の[[CanPut]]内部メソッドを呼び出した結果が の場合、 OPfalse
    • の場合、例外をスローしThrowます。trueTypeError
    • それ以外の場合は戻ります。

...

[[CanPut]]false配列の場合、[[Extensible]]onOがの場合は、特に返されますfalse

したがって、ChromeはECMA 262 5.1 仕様に違反しています。

アップデート:

Chrome 開発者は、を厳密モードpushで実行することについて話し合っています。ただし、 ECMA 262 5.1 仕様で非常に具体的に指定されている動作として、pop「厳密」と「非厳密」の違いだけではありません。pushpop

于 2013-08-13T06:11:59.340 に答える