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
Motive behind strict mode syntax error when deleting an unqualified identifier?
提问by Dagg Nabbit
I'm having trouble understanding why, in strict mode, a syntax error occurs when delete
is used on an unqualified identifier.
我无法理解为什么在严格模式下,当delete
用于非限定标识符时会出现语法错误。
In most cases, it makes sense... if you are declaring variables in the usual way with the var
keyword, and then trying to use delete
on 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 delete
on 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 eval
calls have their own scope in strict mode, instead of the calling function's scope, so in the third example foo
would 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 段。规格:
- 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.
- 否则, 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 new
operator isn't used this
is 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