如何取消设置 JavaScript 变量?

我在JavaScript中有一个全局变量(实际上是一个属性,但我认为这并不重要),它已经被以前的脚本填充了,但我不希望另一个稍后运行的脚本看到它的值,或者它甚至被定义了。window

我已经放了,它适用于测试的目的,但我真的不认为这是正确的方法。some_var = undefinedtypeof some_var == "undefined"

你觉得怎么样?


答案 1

运算符从对象中删除属性。它无法删除变量。因此,问题的答案取决于如何定义全局变量或属性。delete

(1) 如果是使用 创建,则无法删除。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

技术说明

1. 使用var

在这种情况下,引用是在 ECMAScript 规范称为“变量环境”的内容中创建的,该规范附加到当前作用域 - 这可能是在函数内部使用的情况下的函数执行上下文(尽管当您考虑时可能会变得有点复杂),或者在“全局”代码的情况下,变量环境被附加到全局对象(通常)。g_avarletwindow

变量环境中的引用通常是不可删除的 - ECMAScript 10.5 中详细介绍的过程对此进行了详细解释,但足以说明,除非您的代码在上下文中执行(大多数基于浏览器的开发控制台都使用),否则无法删除声明的变量。evalvar

2. 不使用var

当尝试在不使用关键字的情况下为名称赋值时,JavaScript 会尝试在 ECMAScript 规范称为“LexicalEnvironment”的地方找到命名引用,主要区别在于 LexicalEnvironments 是嵌套的 - 即 LexicalEnvironment 有一个父级(ECMAScript 规范称之为“外部环境引用”),并且当 JavaScript 无法在 LexicalEnvironment 中找到引用时, 它查找父词法环境中(详见 10.3.110.2.2.1)。顶级词法环境是“全局环境”,它绑定到全局对象,因为它的引用是全局对象的属性。因此,如果您尝试访问未使用当前作用域或任何外部作用域中的关键字声明的名称,JavaScript 最终将获取该对象的属性以用作该引用。正如我们之前所了解的,可以删除对象的属性。varvarwindow

笔记

  1. 重要的是要记住,声明是“吊装的” - 即它们总是被认为是在它们所在的范围的开始时发生的 - 尽管不是可能在语句中完成的值初始化 - 它被留在原处。因此,在下面的代码中,是来自 VariableEnvironment 的引用,而不是属性,其值将位于代码的末尾:varvarawindow10

    function test() { a = 5; var a = 10; }
    
  2. 上面的讨论是当“严格模式”未启用时。使用“严格模式”时,查找规则略有不同,如果没有“严格模式”,则解析为窗口属性的词法引用将在“严格模式”下引发“未声明的变量”错误。我并不真正理解这是在哪里指定的,但它是浏览器的行为方式。


答案 2

scunliffe的答案会起作用,但从技术上讲,它应该是

delete window.some_var;

当目标不是对象属性时,delete 应该是 no-op。例如,

(function() {
   var foo = 123;
   delete foo; // wont do anything, foo is still 123
   var bar = { foo: 123 };
   delete bar.foo; // foo is gone
}());

但是由于全局变量实际上是窗口对象的成员,因此它可以工作。

当涉及原型链时,使用 delete 会变得更加复杂,因为它只会从目标对象中删除属性,而不会从原型中删除。例如,

function Foo() {}
Foo.prototype = { bar: 123 };
var foo = new Foo();
// foo.bar is 123
foo.bar = 456;
// foo.bar is now 456
delete foo.bar;
// foo.bar is 123 again.

所以要小心。

注意:我的答案有些不准确(见最后的“误解”)。该链接解释了所有血腥的细节,但摘要是浏览器之间可能存在很大差异,具体取决于您要从中删除的对象。 一般应该是安全的,只要。我仍然不会使用它来删除声明的变量,尽管您可以在适当的情况下使用。delete object.somePropobject !== windowvar