为什么`'foo" .bar = 42;`在ES6中以严格模式抛出`TypeError`? [英] Why does `"foo".bar = 42;` throw `TypeError` in strict mode in ES6?

查看:107
本文介绍了为什么`'foo" .bar = 42;`在ES6中以严格模式抛出`TypeError`?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据ES5.1规范,程序use strict; foo.bar = 42; 导致创建一个 String 对象,分配给它上面的属性,然后抛弃该对象,导致没有可观察到的影响 - 包括任何例外。 (没有效果可以通过在与Opera 12中的ES5兼容的JS实现中尝试来确认。)

According to the ES5.1 spec, the program "use strict;" "foo".bar = 42; causes a String object to be created, assigns to a property on it, and then throws the object away, resulting in no observable effects - including any exceptions. (The absence of effect can be confirmed by trying it in an ES5-compatible JS implementation like that in Opera 12.)

在现代JS实现中,它会抛出 TypeError 而不是试试:

In modern JS implementations, it throws a TypeError instead—try it:

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

我很确定ES6规范规定了新的行为,但是尽管多次阅读相关部分,但我无法看到指定 TypeError 被抛出的位置。事实上,关键部分似乎是不变:

I am pretty sure the new behaviour is mandated by the ES6 spec, but despite reading the relevant sections several times I cannot see where it is specified that TypeError be thrown. In fact, the key parts appear to be unchanged:


6.2.3.2 PutValue( V W )#


  1. ReturnIfAbrupt( V )。

  2. ReturnIfAbrupt( W )。

  3. 如果Type( V )不是Reference,则抛出 ReferenceError 异常。

  4. base 为GetBase( V )。

  5. 如果IsUnresolvableReference( V )是的,然后是


    • ...

  1. ReturnIfAbrupt(V).
  2. ReturnIfAbrupt(W).
  3. If Type(V) is not Reference, throw a ReferenceError exception.
  4. Let base be GetBase(V).
  5. If IsUnresolvableReference(V) is true, then

  • a。如果HasPrimitiveBase( V )为真,那么


    • i。断言:在这种情况下, base 永远不会为null或未定义。

    • ii。将 base 设置为ToObject( base )。

    • a. If HasPrimitiveBase(V) is true, then
      • i. Assert: In this case, base will never be null or undefined.
      • ii. Set base to ToObject(base).


      规范(ES6或更高版本)在哪里强制抛出 TypeError

      Where does the spec (ES6 or later) mandate throwing TypeError?

      推荐答案

      我想它就在这里:

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


      9.1.9.1。 OrdinarySet(O,P,V,Receiver)

      9.1.9.1. OrdinarySet (O, P, V, Receiver)

      [...]

      4.b。如果Type(Receiver)不是Object,则返回false。

      4.b. If Type(Receiver) is not Object, return false.

      (以前称为[[Set]],在ES6§9.1.9。)

      (Previously called [[Set]], in ES6 §9.1.9.)

      虽然 PutValue 促销 base 到一个对象,它与接收者不一样 - GetThisValue(V)仍在原始<$ c上调用$ c> V (带有原始基数)。所以, GetThisValue 返回一个原语, OrdinarySet.4b 无法分配新创建的 ownDesc 并返回 false ,这反过来导致 PutValue.6d 抛出一个TypeError,提供参考是严格的。

      Although PutValue promotes the base to an object, it doesn't do the same with the receiver -- GetThisValue(V) is still called on the original V (with a primitive base). So, GetThisValue returns a primitive, OrdinarySet.4b fails to assign a freshly created ownDesc and returns false, and this in turn causes PutValue.6d to throw a TypeError, provided the reference is strict.

      V8的相应部分似乎遵循相同的逻辑:

      The corresponding part of V8 seems to follow the same logic:

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

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

      这篇关于为什么`'foo&quot; .bar = 42;`在ES6中以严格模式抛出`TypeError`?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆