我在 JavaScript 中有一个全局变量(实际上是一个window属性,但我认为这并不重要),它已经由以前的脚本填充,但我不希望稍后运行另一个脚本来查看它的值或者它是甚至定义。
window
我已经提出some_var = undefined并且它可以用于测试目的,typeof some_var == "undefined"但我真的认为这不是正确的方法。
some_var = undefined
typeof some_var == "undefined"
你怎么看?
操作员从对象中delete删除属性。它不能删除变量。所以问题的答案取决于全局变量或属性是如何定义的。
delete
(1) 如果用 创建var,则不能删除。
var
例如:
var g_a = 1; //create with var, g_a is a variable delete g_a; //return false console.log(g_a); //g_a is still 1
(2) 如果创建时不带var,则可以删除。
g_b = 1; //create without var, g_b is a property delete g_b; //return true console.log(g_b); //error, g_b is not defined
在这种情况下,引用g_a是在 ECMAScript 规范所称的“ VariableEnvironment ”中创建的,它附加到当前范围 - 这可能是在函数var内部使用的情况下的函数执行上下文(尽管它可能会变得有点复杂当您考虑时let)或在“全局”代码的情况下, VariableEnvironment 附加到全局对象(通常window)。
g_a
let
VariableEnvironment 中的引用通常不可删除 - ECMAScript 10.5中详述的过程详细解释了这一点,但足以说明除非您的代码在eval上下文中执行(大多数基于浏览器的开发控制台使用),否则声明的变量var不能被删除。
eval
当试图在不使用var关键字的情况下为名称分配值时,JavaScript 会尝试在 ECMAScript 规范所称的“ LexicalEnvironment ”中定位命名引用,主要区别在于 LexicalEnvironment 是嵌套的——即 LexicalEnvironment 有一个父级 ( ECMAScript 规范称为“外部环境引用”),当 JavaScript 无法在 LexicalEnvironment 中找到引用时,它会在父 LexicalEnvironment 中查找(详见10.3.1和10.2.2.1)。顶层 LexicalEnvironment 是“ 全局环境” “,并且绑定到全局对象,因为它的引用是全局对象的属性。因此,如果您尝试访问未var在当前作用域或任何外部作用域中使用关键字声明的名称,JavaScript 最终将获取一个属性对象的window属性作为引用。正如我们之前所学的,对象的属性可以被删除。
重要的是要记住var声明是“提升的”——即它们总是被认为发生在它们所在范围的开头——尽管不是可以在var语句中完成的值初始化——它被留在原处. 所以在下面的代码中,a是来自 VariableEnvironment 而不是window属性的引用,它的值将10在代码的末尾:
a
10
function test() { a = 5; var a = 10; }
上面的讨论是没有启用“严格模式”的情况。使用“严格模式”时查找规则有点不同,在没有“严格模式”的情况下解析为窗口属性的词法引用将在“严格模式”下引发“未声明的变量”错误。我真的不明白这是在哪里指定的,但它是浏览器的行为方式。