如何取消设置JavaScript变量?

我在JavaScript中有一个全局变量(其实是一个window属性,但我认为这并不重要),该变量已经由先前的脚本填充,可是我不但愿另外一个稍后运行的脚原本查看其值或甚至定义。 浏览器

我已经放了some_var = undefined ,它能够用于测试typeof some_var == "undefined"可是我真的不认为这是正确的方法。 安全

你怎么看? 函数


#1楼

some_var = null;

//or remove it..
delete some_var;

#2楼

若是您隐式声明不带var的变量,则正确的方法是使用delete foo测试

可是,在删除它以后,若是尝试在诸如加法之类的操做中使用它,则会抛出ReferenceError由于您没法将字符串添加到未声明,未定义的标识符中。 例: spa

x = 5;
delete x
alert('foo' + x )
// ReferenceError: x is not defined

在某些状况下,将其分配为false,null或undefined可能更为安全,所以将其声明且不会引起此类错误。 prototype

foo = false

请注意,在ECMAScript中, nullfalseundefined0NaN''都将取值为false 。 只要确保您不使用!==运算符,而是使用!=来进行布尔类型的类型检查而且您不但愿进行身份检查(所以null== falsefalse == undefined )。 code

还要注意, 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声明了变量,则没法删除它: ip

(function() {
    var x = 5;
    alert(delete x)
    // false
})();

在犀牛中: ci

js> var x
js> delete x
false

您也不能删除一些预约义的属性,例如Math.PI

js> delete Math.PI
false

与任何语言同样,有一些奇怪的例外要delete ,若是您足够关心,则应阅读:


#3楼

@scunlife的答案会起做用,但从技术上讲应该是

delete window.some_var;

当目标不是对象属性时,delete应该被禁止使用。 例如,

(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.

因此要当心

编辑:个人回答有点不许确 (请参阅末尾的“误解”)。 该连接说明了全部详细信息,但摘要是,浏览器之间以及要删除的对象之间可能会有很大差别。 只要object !== window delete object.someProp一般应该是安全的。 尽管您能够在适当的状况下使用,但我仍然不会使用它来删除用var声明的变量。


#4楼

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

在这种状况下,引用g_a是在ECMAScript规范称为“ VariableEnvironment ”的状况下建立的,该引用附加到当前做用域-在函数内部使用var的状况下,这多是函数执行上下文(尽管可能会获得一些帮助)当您考虑let )或在“全局”代码的状况下, 变量环境更加复杂, 变量环境被附加到全局对象(一般是window )。

VariableEnvironment中的引用一般是不可删除的-ECMAScript 10.5中详细介绍的过程对此进行了详细说明,但能够这样说,除非您的代码在eval上下文中执行(大多数基于浏览器的开发控制台都使用该上下文),而后使用var没法删除。

2.不使用var

当尝试在不使用var关键字的状况下为名称分配值时,Javascript尝试在ECMAScript规范称为“ LexicalEnvironment ”的位置查找命名的引用,主要区别在于LexicalEvironment是嵌套的-LexicalEnvironment有一个父项(ECMAScript规范称为“外部环境引用”),而且当Javscript没法在LexicalEenvironment中找到引用时,它将在父LexicalEnvironment中查找(如10.3.110.2.2.1中所述 )。 顶级LexicalEnvironment是“ 全局环境 ”,它绑定到全局对象,由于它的引用是全局对象的属性。 所以,若是您尝试访问在当前范围或任何外部范围中未使用var关键字声明的名称,则Javascript最终将获取window对象的属性以用做该引用。 正如咱们以前所了解的,能够删除对象的属性。

笔记

  1. 重要的是要记住var声明是“悬挂的”-即始终认为它们已在它们所在范围的开头发生-尽管不是在var语句中可能完成的值初始化-留在了它是。 所以,在如下代码中, aVariableEnvironment的引用,而不是window属性的引用,在代码末尾,其值为10

    function test() { a = 5; var a = 10; }

  2. 以上讨论是在未启用“严格模式”的状况下。 使用“严格模式”时,查找规则略有不一样,若是没有“严格模式”就能够解析为窗口属性的词法引用将在“严格模式”下引起“未声明变量”错误。 我不太了解在哪里指定它,可是它在浏览器中的表现如何。


#5楼

除了每一个人都写的内容外,还请注意delete返回布尔值。 它能够告诉您删除是否成功。

在Chrome上进行测试,除let以外的全部内容均可以删除。 当delete返回true ,实际上删除了它们:

implicit_global = 1;
window.explicit_global = 1;
function_set = function() {};
function function_dec() { };
var declared_variable = 1;
let let_variable = 1;

delete delete implicit_global; // true, tested on Chrome 52
delete window.explicit_global; // true, tested on Chrome 52
delete function_set; // true, tested on Chrome 52
delete function_dec; // true, tested on Chrome 52
delete declared_variable; // true, tested on Chrome 52
delete let_variable; // false, tested on Chrome 78
相关文章
相关标签/搜索