删除非限定标识符时,严格模式语法错误背后的动机是什么?

Dag*_*bit 15 javascript ecmascript-5

我无法理解为什么在严格模式下,delete在非限定标识符上使用时会出现语法错误.

在大多数情况下,它是有道理的...如果你用通常的方式用var关键字声明变量,然后尝试使用delete它们,在非严格模式下它会无声地失败,所以严格模式失败是有意义的在这些情况下有错误.

不过,也有在那里你的情况下无法删除该标识符合格的:

(function() {

  // "use strict";

  var obj = Object.create({}, { bloop: { configurable: false } });

  delete obj.bloop; // throws TypeError in strict mode, silently fails in non-strict.

  console.log('bloop' in obj); // true

}());
Run Code Online (Sandbox Code Playgroud)

严格模式必须在此处执行运行时检查,因为遇到此类型时会引发TypeError.在某些情况下,您可以在非严格模式下成功删除非限定标识符...

// "use strict";

window.bar = 6;

console.log(typeof bar); // number

delete bar; // works in non-strict, syntax error in strict!

console.log(typeof bar); // undefined
Run Code Online (Sandbox Code Playgroud)

事实上,根据我的理解,您是否可以删除内容(在非严格模式下)取决于内部[[Configurable]]属性,并且与限定标识符无关.据我所知,在严格模式下无法删除非全局变量(作为本地VO的属性)是可配置的:

(function() {

  // "use strict";

  eval('var foo = 5;');

  console.log(typeof foo); // number

  delete foo; // works in non-strict, SyntaxError in strict.

  console.log(typeof foo); // undefined

}());
Run Code Online (Sandbox Code Playgroud)

所以,我的问题是,当delete在非限定标识符上使用时抛出SyntaxError有什么意义,当TypeError无论如何都会抛出属性不可配置时会抛出什么?这似乎是一个不必要的限制,在某些情况下似乎没有任何解决方法,除了不使用严格模式(第三个例子).谁能解释这个决定背后的动机?


更新:我刚刚意识到我忽略了这样一个事实:直接eval调用在严格模式下有自己的范围,而不是调用函数的范围,所以在第三个例子中foo不会在严格模式下定义.无论如何,运行时检查仍然会捕获这一点,但它提出了一个侧面问题:是否没有办法在严格模式下使用可配置的局部变量,就像eval在非严格模式中使用'd变量声明一样?AFAIK是少数合法用途之一eval.

use*_*621 6

你在谈论第11.4.1节,第5.a节.规格:

  1. 否则,ref是对环境记录绑定的引用,所以
    a.如果IsStrictReference(ref)为true,则抛出SyntaxError异常.
    湾 让绑定成为GetBase(ref).
    C.返回调用DeleteBinding具体绑定方法的结果,提供GetReferencedName(ref)作为参数.

你所谓的"不合格标识符"正式命名为"环境记录绑定".

现在,问你的问题.为什么在5.c.时抛出一个SyntaxError.反正会失败吗?我想你自己回答了!

严格模式必须在此处执行运行时检查,因为遇到此类型时会引发TypeError .

那就对了.但快速失败总是更好.因此,当有可能检测到SyntaxError(在分析时)时,应该采取这种机会.

为什么?如果发生错误,它可以帮您省去修复应用程序的麻烦.考虑可能会立即向您显示错误的IDE,而不是数小时的调试.
而且,这种限制对于优化的JIT编译器可能是有利的.