JavaScript 的严格模式对于隐式全局声明到底做了什么?
What does JavaScript's strict mode exactly do regarding implicit global declarations?
来自MDN article about strict mode:
First, strict mode makes it impossible to accidentally create global
variables. In normal JavaScript mistyping a variable in an assignment
creates a new property on the global object and continues to "work"
(although future failure is possible: likely, in modern JavaScript).
Assignments, which would accidentally create global variables, instead
throw an error in strict mode:
'use strict';
// Assuming a global variable mistypedVariable exists
mistypeVariable = 17; // this line throws a ReferenceError due to the
// misspelling of variable
这是什么意思? 引擎是否检测是否已经存在具有相似名称的变量(?!)或者严格模式是否仅仅禁止在全局范围之外声明全局变量?
上面的引述似乎暗示了第一种可能性,但这似乎……很奇怪?
引用代码中的注释具有误导性:"Assuming" 部分无关紧要。它应该真的是:"Assuming that no global variable with exactly this name was defined with let
or var
,..."
但请注意代码片段和注释的目的:表明在严格模式下更容易发现拼写错误。在草率模式下,拼写错误不会被注意到(没有错误),并且您会在不知不觉中使用两个变量(至少有一段时间)
does strict mode merely prohibit declaring global variables outside of global scope?
严格模式绝对不禁止从任何地方声明全局变量。在非严格模式下,如果你写:
someVar = 't';
它将评估为:
window.someVar = 't';
( why is this happening? ) 尽管在函数作用域内部或外部写入。实际上,该行是变量的声明和评估(再看一遍,它没有 var
所以它不应该声明任何东西!)。
但这会导致这样的副作用,这并不完全好,他们引入了严格模式,当它处于活动状态时,我们的第一行会抛出错误。因为它只是评估而没有先声明它。
现在如果你需要在函数范围内操作全局范围,你只需要全局对象作为参考:
var someGlobalVar;
var someOtherGlobalVar;
function hello() {
// this will make *someGlobalVar* to be redefined in the inner scope
// someGlobalVar != window.someGlobalVar
var someGlobalVar;
// manipulating inner variable, not global one
someGlobalVar = 's';
// it's fine, you've accessed global object correctly
window.someGlobalVar = 's';
// you're still editing global object, because
// there's no other variable inside of this scope having the same name
someOtherGlobalVar = 's';
}
根据要求,我会把它变成一个答案:)
我认为您已经了解这里发生的事情,并且只是通过字面上阅读有关 "assuming a global variable..." 的引述而感到困惑。 (我承认它的措辞方式可能会导致这种混淆。)实际情况非常简单,与具有 "similar names" 的变量无关(JS 没有这个概念):
这里讨论的是,如果您将一个值赋给一个尚未正式声明的变量(变量是使用关键字 var
、let
或 const
).不声明你的变量是不好的做法,在严格模式下会抛出一个错误 - 这是一件好事并警告你你的错误。但是在非严格模式下,JS 会很乐意接受这个并认为你想声明一个 global 那个名字的变量。这几乎不是您真正想要的,因为它污染了全局名称空间,不会通知您您的错误,并且可能会在以后导致各种棘手的错误。
来自MDN article about strict mode:
First, strict mode makes it impossible to accidentally create global variables. In normal JavaScript mistyping a variable in an assignment creates a new property on the global object and continues to "work" (although future failure is possible: likely, in modern JavaScript). Assignments, which would accidentally create global variables, instead throw an error in strict mode:
'use strict'; // Assuming a global variable mistypedVariable exists mistypeVariable = 17; // this line throws a ReferenceError due to the // misspelling of variable
这是什么意思? 引擎是否检测是否已经存在具有相似名称的变量(?!)或者严格模式是否仅仅禁止在全局范围之外声明全局变量?
上面的引述似乎暗示了第一种可能性,但这似乎……很奇怪?
引用代码中的注释具有误导性:"Assuming" 部分无关紧要。它应该真的是:"Assuming that no global variable with exactly this name was defined with let
or var
,..."
但请注意代码片段和注释的目的:表明在严格模式下更容易发现拼写错误。在草率模式下,拼写错误不会被注意到(没有错误),并且您会在不知不觉中使用两个变量(至少有一段时间)
does strict mode merely prohibit declaring global variables outside of global scope?
严格模式绝对不禁止从任何地方声明全局变量。在非严格模式下,如果你写:
someVar = 't';
它将评估为:
window.someVar = 't';
( why is this happening? ) 尽管在函数作用域内部或外部写入。实际上,该行是变量的声明和评估(再看一遍,它没有 var
所以它不应该声明任何东西!)。
但这会导致这样的副作用,这并不完全好,他们引入了严格模式,当它处于活动状态时,我们的第一行会抛出错误。因为它只是评估而没有先声明它。
现在如果你需要在函数范围内操作全局范围,你只需要全局对象作为参考:
var someGlobalVar;
var someOtherGlobalVar;
function hello() {
// this will make *someGlobalVar* to be redefined in the inner scope
// someGlobalVar != window.someGlobalVar
var someGlobalVar;
// manipulating inner variable, not global one
someGlobalVar = 's';
// it's fine, you've accessed global object correctly
window.someGlobalVar = 's';
// you're still editing global object, because
// there's no other variable inside of this scope having the same name
someOtherGlobalVar = 's';
}
根据要求,我会把它变成一个答案:)
我认为您已经了解这里发生的事情,并且只是通过字面上阅读有关 "assuming a global variable..." 的引述而感到困惑。 (我承认它的措辞方式可能会导致这种混淆。)实际情况非常简单,与具有 "similar names" 的变量无关(JS 没有这个概念):
这里讨论的是,如果您将一个值赋给一个尚未正式声明的变量(变量是使用关键字 var
、let
或 const
).不声明你的变量是不好的做法,在严格模式下会抛出一个错误 - 这是一件好事并警告你你的错误。但是在非严格模式下,JS 会很乐意接受这个并认为你想声明一个 global 那个名字的变量。这几乎不是您真正想要的,因为它污染了全局名称空间,不会通知您您的错误,并且可能会在以后导致各种棘手的错误。