Javascript 为什么`";“福”;。bar=42;`在ES6中以严格模式抛出'TypeError'?

Javascript 为什么`";“福”;。bar=42;`在ES6中以严格模式抛出'TypeError'?,javascript,ecmascript-6,typeerror,ecmascript-5,primitive,Javascript,Ecmascript 6,Typeerror,Ecmascript 5,Primitive,根据ES5.1规范,程序“严格使用”,“foo”.bar=42导致创建一个字符串对象,将其指定给该对象上的属性,然后将该对象丢弃,从而不会产生任何可观察的效果,包括任何异常。(可以通过在兼容ES5的JS实现(如Opera 12中的实现)中尝试来确认没有效果。) 在现代JS实现中,它抛出一个TypeError,而不是尝试: “严格使用”;“foo”,bar=42我猜它在这里: 9.1.9.1。普通组(O、P、V、接收器) [……] 4.b。如果Type(Receiver)不是Object,则返

根据ES5.1规范,程序
“严格使用”,“foo”.bar=42导致创建一个
字符串
对象,将其指定给该对象上的属性,然后将该对象丢弃,从而不会产生任何可观察的效果,包括任何异常。(可以通过在兼容ES5的JS实现(如Opera 12中的实现)中尝试来确认没有效果。)

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

“严格使用”;“foo”,bar=42我猜它在这里:

9.1.9.1。普通组(O、P、V、接收器)

[……]

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

(以前在中称为[[Set]])

虽然
PutValue
base
提升为一个对象,但它对接收方的作用不同--
GetThisValue(V)
仍在原始
V
上调用(使用基元基)。因此,
GetThisValue
返回一个原语,
OrdinarySet.4b
无法分配一个新创建的
ownDesc
并返回
false
,这反过来会导致
PutValue.6d
抛出一个类型错误,只要引用是严格的

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

Maybe<bool> Object::AddDataProperty(....
  if (!it->GetReceiver()->IsJSReceiver()) {
    return CannotCreateProperty(...
可能对象::AddDataProperty(。。。。
如果(!it->GetReceiver()->IsJSReceiver()){
返回CannotCreateProperty(。。。

@georg的答案似乎是正确的ES6+解释,但这种行为似乎也不是什么新鲜事。来源:

  • 否则,如果IsPropertyReference(V),则

    a、 如果HasPrimitiveBase(V)为false,那么让put成为base的[[put]]内部方法,否则让put成为特殊的[[put]] 内部方法定义如下

    b、 使用base作为其this值调用put内部方法,并传递GetReferencedName(V)作为属性名,传递W作为值, 和投掷标志的ISTrictReference(V)

  • 在引用的[[Put]]中:

  • 否则,这是一个在瞬态对象O上创建自己属性的请求

    a、 如果Throw为true,则抛出TypeError异常


  • 感觉上我可能是误读了一些东西……但还有什么可能是比较尖锐的“这是一个在瞬态对象O上创建自己属性的请求”是指?

    我也没有在中看到它。我开始怀疑它实际上根本不在规范中。这里是它进入V8的地方,与往常一样没有参考:现在看看其他人。我的期望是
    ToObject
    将显式返回一个不可扩展的
    字符串,因此
    [[Set]]
    将返回false,步骤6将抛出,但我实际上没有看到它定义字符串对象是不可扩展的。@Paulpro:创建字符串对象,使用
    对象将其设置为不可扩展。preventExtensions
    ,并尝试在严格模式下对其设置属性,会为我生成不同的错误消息,其中一个例子“对象不可扩展"。对于问题中的情况,它似乎根本没有穿过一个对象。它不应该到达那里,因为
    ownDesc
    应该是未定义的。那又怎样?步骤3没有返回。很好的发现,在我看来是正确的。它将遍历原型,最终到达顶层,创建一个数据描述符,并尝试在接收端设置它r、 这仍然是最原始的。是的,最好扩展它来提到
    6.d
    ,尽管这已经包含在问题中。奇怪的是,这似乎没有包含在附录C中。附录C只是提供了信息,但仍然很奇怪。这是一个很好的观察结果。我不确定在检查ES时我是如何忽略了这一点的5.1规范,但看起来Opera 12开发人员也这么做了。