javascript 删除不合格标识符时严格模式语法错误背后的动机?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10643587/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 10:32:28  来源:igfitidea点击:

Motive behind strict mode syntax error when deleting an unqualified identifier?

javascriptecmascript-5

提问by Dagg Nabbit

I'm having trouble understanding why, in strict mode, a syntax error occurs when deleteis used on an unqualified identifier.

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

In most cases, it makes sense... if you are declaring variables in the usual way with the varkeyword, and then trying to use deleteon them, in non-strict mode it would silently fail, so it makes sense for strict mode to fail with an error in those cases.

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

However, there are cases where you can'tdelete identifiers that arequalified:

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

(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

}());

Strict mode must do a runtime check here, because a TypeError is thrown when this is encountered. There are also cases where you cansuccessfully delete unqualified identifiers in non-strict mode...

严格模式必须在此处进行运行时检查,因为遇到这种情况时会抛出 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

In fact, to my understanding, whether or not you can delete things (in non-strict mode) depends on the internal [[Configurable]]property, and has nothing to do with qualified identifiers. As far as I can tell, there is no way in strict mode to delete non-global variables that (as properties of the local VO) areconfigurable:

其实据我了解,能不能删除东西(非严格模式下)取决于内部[[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

}());

So, my question is, what's the point of throwing a SyntaxError when using deleteon an unqualified identifier, when the TypeError would throw anyway if the property is not configurable? This seems like an unnecessary restriction, and in some cases there doesn't seem to be any workaround other than not using strict mode (third example). Can anyone explain the motivation behind this decision?

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



Update: I just realized that I was overlooking the fact that direct evalcalls have their own scope in strict mode, instead of the calling function's scope, so in the third example foowould not be defined under strict mode. Anyway, the runtime check would still catch this, but it raises a side question: Is there no way to have configurable local variables in strict mode, as we do with eval'd variable declarations in non-strict? AFAIK that was one of the few legitimate uses of eval.

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

采纳答案by user123444555621

You are talking about Section 11.4.1, paragraph 5.a.of the specs:

您指的是第 11.4.1 节第 5.a 段。规格:

  1. Else, ref is a Reference to an Environment Record binding, so
    a. If IsStrictReference(ref) is true, throw a SyntaxError exception.
    b. Let bindings be GetBase(ref).
    c. Return the result of calling the DeleteBinding concrete method of bindings, providing GetReferencedName(ref) as the argument.
  1. 否则, ref 是对环境记录绑定的引用,因此
    a. 如果 IsStrictReference(ref) 为 true,则抛出 SyntaxError 异常。
    湾 让绑定为 GetBase(ref)。
    C。返回调用绑定的DeleteBinding 具体方法的结果,提供GetReferencedName(ref) 作为参数。

What you called "unqualified identifiers" is officially named "Environment Record binding".

您所谓的“不合格标识符”正式命名为“环境记录绑定”。

Now, to your question. Why throw a SyntaxError when 5.c. would fail anyway? I think you answered it yourself!

现在,回答你的问题。为什么在 5.c. 时抛出 SyntaxError 无论如何都会失败?我想你自己回答了!

Strict mode must do a runtime checkhere, because a TypeError is thrown when this is encountered.

严格模式必须在这里进行运行时检查,因为遇到这种情况时会抛出 TypeError 。

That's right. But it's always better to fail fast. So, when there is a chance of detecting a SyntaxError (at parse time), that opportunity should be taken.

那就对了。但快速失败总是更好的。因此,当有机会检测到 SyntaxError(在解析时)时,应该抓住这个机会。

Why? It saves you the trouble of fixing your app if an error occurs. Think about IDEs that may show you the error right away, as opposed to hours of debugging.
Also, such restrictions may be advantageous for optimized JIT compilers.

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

回答by rda3mon

If you want to delete object in strict mode. You have to explicitly mention about the property access. Also note that, how you call the function is important. If newoperator isn't used thisis undefined under use strict, and you cant use the below method. Example:

如果要在严格模式下删除对象。您必须明确提及属性访问权限。另请注意,调用函数的方式很重要。如果new未使用运算符this在 下未定义use strict,则不能使用以下方法。例子:

'use strict'
function func(){
  var self = this;
  self.obj = {};
  self.obj.x = 'y'

  console.log(self.obj);
  delete self.obj // works
  // delete obj // doesn't work
  console.log(self.obj);
}

var f = new func();

For deleting object outside of the function(closure), you will have to call like

要删除函数(闭包)之外的对象,您必须像这样调用

// same code as above
delete f.obj