为什么``foo“.bar = 42;`在ES6中以严格模式抛出`TypeError`?

时间:2018-04-05 22:46:51

标签: javascript ecmascript-6 typeerror ecmascript-5 primitive

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

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

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

我很确定新行为是由ES6规范强制执行的,但是尽管多次阅读相关部分,但我无法看到指定TypeError被抛出的位置。事实上,the key parts似乎没有改变:

  

6.2.3.2 PutValue( V W )#

     
      
  1. ReturnIfAbrupt( V )。
  2.   
  3. ReturnIfAbrupt( w ^ )。
  4.   
  5. 如果Type( V )不是Reference,则抛出 ReferenceError 异常。
  6.   
  7. base 成为GetBase( V )。
  8.   
  9. 如果IsUnresolvableReference( V )为真,那么      
        
    • ...
    •   
  10.   
  11. 如果IsPropertyReference( V )为真,那么      
        
    • 一个。如果HasPrimitiveBase( V )为真,那么      
          
      • 我。断言:在这种情况下, base 永远不会为null或未定义。
      •   
      • II。将 base 设置为ToObject( base )。
      •   
    •   
    • 湾让成功 base 。[[Set]](GetReferencedName( V ), W ,GetThisValue( V ))。< / LI>   
    • ℃。 ReturnIfAbrupt(成功)。
    •   
    • d。如果成功为false且IsStrictReference( V )为true,则抛出 TypeError 异常。
    •   
    • 即回报率。
    •   
  12.   
  13. ...
  14.   

规范(ES6或更高版本)在哪里授权投掷TypeError

2 个答案:

答案 0 :(得分:16)

我想它就在这里:

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

  

9.1.9.1。普通集(O,P,V,接收器)

     

[...]

     

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

(以前在[{3}}中称为[[Set]]。)

虽然PutValuebase提升为某个对象,但它与接收者的行为不同 - GetThisValue(V)仍在原始V上调用(原始基础)。因此,GetThisValue返回一个原语,OrdinarySet.4b无法分配新创建的ownDesc并返回false,这反过来导致PutValue.6d抛出一个TypeError,如果参考是严格的。

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

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

ES6 §9.1.9

答案 1 :(得分:5)

@ georg的答案似乎是正确的ES6 +解释,但看起来这种行为也不是新的。来自ES5.1 PutValue

  
      
  1. 如果是IsPropertyReference(V),那么

         

    一个。如果HasPrimitiveBase(V)为false,那么让put为[base]的[[Put]]内部方法,否则让put为特殊[[Put]]   下面定义的内部方法

         

    湾使用base作为此值调用put internal方法,并为属性名称传递GetReferencedName(V),为值传递W,   投掷标志的和IsStrictReference(V)

  2.   

和引用的[[Put]]:

  
      
  1. 否则,这是在瞬态对象O

    上创建自己的属性的请求      

    一个。如果Throw为true,则抛出TypeError异常。

  2.   

感觉我可能误读了某些东西......但是还有什么可以指出“这是在瞬态对象O上创建自己的属性的请求”指的是什么?