我在 JavaScript 中有一个全局变量(实际上是一个window
属性,但我认为它并不重要)已经由以前的脚本填充,但我不希望另一个脚本稍后运行以查看其值或它是甚至定义。
我已经把some_var = undefined
它用于测试的目的,typeof some_var == "undefined"
但我真的认为这不是正确的方法。
你怎么认为?
我在 JavaScript 中有一个全局变量(实际上是一个window
属性,但我认为它并不重要)已经由以前的脚本填充,但我不希望另一个脚本稍后运行以查看其值或它是甚至定义。
我已经把some_var = undefined
它用于测试的目的,typeof some_var == "undefined"
但我真的认为这不是正确的方法。
你怎么认为?
的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
var
在这种情况下,引用g_a
是在 ECMAScript 规范所称的“ VariableEnvironment ”中创建的,它附加到当前范围 - 在函数var
内部使用的情况下,这可能是函数执行上下文(尽管它可能会变得更复杂一些)当您考虑let
) 或在“全局”代码的情况下,VariableEnvironment附加到全局对象(通常window
)。
VariableEnvironment中的引用通常不可删除——ECMAScript 10.5中详述的过程详细解释了这一点,但足以说明除非您的代码在eval
上下文中执行(大多数基于浏览器的开发控制台使用),否则声明的变量var
不能被删除。
var
当尝试在不使用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
在代码的末尾:
function test() { a = 5; var a = 10; }
上面的讨论是在没有启用“严格模式”的情况下。使用“严格模式”时查找规则略有不同,在没有“严格模式”的情况下解析为窗口属性的词法引用将在“严格模式”下引发“未声明的变量”错误。我真的不明白这是在哪里指定的,但它是浏览器的行为方式。
scunliffe的答案会起作用,但从技术上讲应该是
delete window.some_var;
当目标不是对象属性时,删除应该是空操作。例如,
(function() {
var foo = 123;
delete foo; // wont do anything, foo is still 123
var bar = { foo: 123 };
delete bar.foo; // foo is gone
}());
但是由于全局变量实际上是 window 对象的成员,所以它可以工作。
当涉及原型链时,使用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.someProp
一般应该是安全的,只要object !== window
。我仍然不会使用它来删除声明的变量,var
尽管在适当的情况下可以。
如果您隐式声明变量没有var
,正确的方法是使用delete foo
.
但是,在删除它之后,如果您尝试在诸如添加之类的操作中使用它,则会ReferenceError
抛出 a ,因为您无法向未声明的未定义标识符添加字符串。例子:
x = 5;
delete x
alert('foo' + x )
// ReferenceError: x is not defined
在某些情况下,将它分配给 false、null 或 undefined 可能更安全,因此它被声明并且不会抛出此类错误。
foo = false
请注意,在 ECMAScript 中null
,false
, undefined
, 0
, NaN
, or''
都会评估为false
。只要确保你不使用的!==
运营商,而是!=
当布尔类型检查,你不想身份检查(所以null
会== false
和false == undefined
)。
另请注意,delete
不会“删除”引用,而只是直接在对象上的属性,例如:
bah = {}, foo = {}; bah.ref = foo;
delete bah.ref;
alert( [bah.ref, foo ] )
// ,[object Object] (it deleted the property but not the reference to the other object)
如果你已经声明了一个变量,var
你不能删除它:
(function() {
var x = 5;
alert(delete x)
// false
})();
在犀牛中:
js> var x
js> delete x
false
您也不能删除一些预定义的属性,例如Math.PI
:
js> delete Math.PI
false
delete
任何语言都有一些奇怪的例外,如果你足够关心你应该阅读:
请参阅诺亚的答案以获取完整详细信息
//Option A.) set to null
some_var = null;
//Option B.) set to undefined
some_var = undefined;
//Option C.) remove/delete the variable reference
delete obj.some_var
//if your variable was defined as a global, you'll need to
//qualify the reference with 'window'
delete window.some_var;
参考:
TLDR:简单定义的变量(没有var
, let
, const
)可以用 删除delete
。如果您使用var
, let
, const
- 它们既不能用delete
也不能用 删除Reflect.deleteProperty
。
铬 55:
simpleVar = "1";
"1"
delete simpleVar;
true
simpleVar;
VM439:1 Uncaught ReferenceError: simpleVar is not defined
at <anonymous>:1:1
(anonymous) @ VM439:1
var varVar = "1";
undefined
delete varVar;
false
varVar;
"1"
let letVar = "1";
undefined
delete letVar;
true
letVar;
"1"
const constVar="1";
undefined
delete constVar;
true
constVar;
"1"
Reflect.deleteProperty (window, "constVar");
true
constVar;
"1"
Reflect.deleteProperty (window, "varVar");
false
varVar;
"1"
Reflect.deleteProperty (window, "letVar");
true
letVar;
"1"
Firefox Nightly 53.0a1 显示了相同的行为。