web-dev-qa-db-ja.com

ES6で `" foo ".bar = 42;`が厳密モードで `TypeError`をスローするのはなぜですか?

ES5.1仕様によると、プログラム"use strict;" "foo".bar = 42;により、Stringオブジェクトが作成され、そのプロパティに割り当てられてから、オブジェクトが破棄されます。その結果、例外を含め、観察可能な影響はありません。 (効果がないことは、Opera 12.)のようなES5互換のJS実装で試すことで確認できます。)

最新のJS実装では、代わりにTypeErrorをスローします。試してみてください。

"use strict"; "foo".bar = 42;

新しい動作はES6仕様で義務付けられていると確信していますが、関連するセクションを数回読んだにもかかわらず、TypeErrorがスローされるように指定されている場所がわかりません。実際、 重要な部分 は変更されていないように見えます:

6.2.3.2 PutValue([〜#〜] v [〜#〜][〜#〜] w [〜#〜])#

  1. ReturnIfAbrupt([〜#〜] v [〜#〜])。
  2. ReturnIfAbrupt([〜#〜] w [〜#〜])。
  3. Type([〜#〜] v [〜#〜])が参照でない場合は、ReferenceError例外。
  4. baseをGetBase([〜#〜] v [〜#〜])とします。
  5. IsUnresolvableReference([〜#〜] v [〜#〜])がtrueの場合、
  6. それ以外の場合、IsPropertyReference([〜#〜] v [〜#〜])がtrueの場合、
    • a。 HasPrimitiveBase([〜#〜] v [〜#〜])がtrueの場合、
      • 私。アサート:この場合、baseがnullまたは未定義になることはありません。
      • ii。 baseをToObject(base)に設定します。
    • b。 succeededを? base。[[Set]](GetReferencedName([〜#〜] v [〜#〜])、[〜#〜] w [〜#〜]、GetThisValue([〜#〜] v [〜#〜]))。
    • c。 ReturnIfAbrupt(succeeded)。
    • d。 succeededがfalseで、IsStrictReference([〜#〜] v [〜#〜])がtrueの場合、TypeError例外。
    • e。戻る。

仕様(ES6以降)はどこにTypeErrorを投げることを義務付けていますか?

25
cpcallen

私はそれがここにあると思います:

http://www.ecma-international.org/ecma-262/7.0/#sec-ordinaryset

9.1.9.1。 OrdinarySet(O、P、V、レシーバー)

[...]

4.b. Type(Receiver)がObjectでない場合は、falseを返します。

(以前は[[Set]]と呼ばれていました。 ES6§9.1.9 で。)

PutValuebaseをオブジェクトにプロモートしますが、レシーバーでは同じことを行いません-GetThisValue(V)は元のVで引き続き呼び出されます(プリミティブベース)。したがって、GetThisValueはプリミティブを返し、OrdinarySet.4bは新しく作成されたownDescの割り当てに失敗し、falseを返します。これにより、PutValue.6dがスローされます。参照が厳密である場合、TypeError。

V8の対応する部分は、同じロジックに従っているようです。

Maybe<bool> Object::AddDataProperty(....
  if (!it->GetReceiver()->IsJSReceiver()) {
    return CannotCreateProperty(...

https://github.com/v8/v8/blob/3b39fc4dcdb6593013c497fc9e28a1d73dbcba03/src/objects.cc#L514

16
georg

@georgの答えはES6 +の正しい解釈のようですが、動作も新しいものではないようです。から ES5.1 PutValue

  1. それ以外の場合、IsPropertyReference(V)の場合、

    a。 HasPrimitiveBase(V)がfalseの場合、putをベースの[[Put]]内部メソッドとし、それ以外の場合、putを以下に定義する特別な[[Put]]内部メソッドとします

    b。この値としてbaseを使用し、プロパティ名にGetReferencedName(V)、値にW、、ThrowフラグにIsStrictReference(V)を渡して、put内部メソッドを呼び出します。

参照されている[[Put]]:

  1. それ以外の場合、これは一時オブジェクトOに独自のプロパティを作成するためのリクエストです。

    a。 Throwがtrueの場合、TypeError例外をスローします。

おそらく何かを読み間違えているように感じます…しかし、「これは一時オブジェクトOに独自のプロパティを作成するリクエストです」という、他に何を指しているのでしょうか。

5
Ry-