如何取消设置JavaScriptvariables?

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

我已经把some_var = undefined ,它的工作目的是testingtypeof some_var == "undefined"但我真的不认为这是正确的方式去做。

你怎么看?

我知道这是一个古老的线索,但select的答案对我来说还不够清楚。

重点是删除操作从一个对象中删除一个属性。 它不能删除一个variables。 所以问题的答案取决于如何定义全局variables或属性。

(1)如果使用var创build,则不能删除。

例如:

 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)如果没有创buildvar,可以删除。

 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 ”中附加到当前作用域的情况下创build的 – 在使用函数内部的var的情况下,这可能是一个函数执行上下文(虽然可能会稍微当考虑let时更复杂),或者在“全局”代码的情况下, VariableEnvironment被附加到全局对象(通常是window )。

variables环境中的引用通常是不可删除的 – ECMAScript 10.5中详细介绍的过程对此进行了详细解释,但足以说明,除非您的代码在eval上下文中执行(大多数基于浏览器的开发控制台都使用该上下文) var不能被删除。

2.没有使用var

当试图在不使用var关键字的情况下为一个名称赋值时,Javascript会尝试在ECMAScript规范所称的“ LexicalEnvironment ”中定位指定的引用,主要区别在于LexicalEvironment是嵌套的 – 这是LexicalEnvironment的父类(ECMAScript规范称之为“外部环境引用”),并且当Javscript未能在LexicalEenvironment中find引用时,它会在父LexicalEnvironment中查找(详见10.3.1和10.2.2.1 )。 顶级LexicalEnvironment是“ 全局环境 ”,并且绑定到全局对象,因为它的引用是全局对象的属性。 因此,如果您尝试访问未在当前作用域或外部作用域中使用var关键字声明的名称,则JavaScript将最终获取window对象的属性以用作该引用。 正如我们以前所学,对象的属性可以被删除。

笔记

  1. 重要的是要记住, var声明是“悬挂的” – 即它们总是被认为是在它们所在的范围的开始处发生的 – 尽pipe不是可以在var语句中完成的值初始化 -它是。 所以在下面的代码中, a是来自VariableEnvironment的引用,而不是window属性,它的值在代码的末尾是10

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

  2. 上面的讨论是当“严格模式”没有启用。 当使用“严格模式”时,查找规则有些不同,如果没有“严格模式”,会在“严格模式”下引发“未声明variables”错误,而parsing为窗口属性的词法引用也会有所不同。 我真的不明白在哪里指定,但它的浏览器如何performance。

@ scunlife的答案将起作用,但技术上应该是

 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 }()); 

但是因为全局variables实际上是窗口对象的成员,所以它起作用。

当涉及到原型链时,使用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声明的variables,尽pipe你可以在正确的情况下。

如果你隐式地声明没有var的variables,正确的方法是使用delete foo

但是,在删除它之后,如果尝试在添加操作中使用此操作,则会引发ReferenceError因为您无法将string添加到未声明的未定义标识符。 例:

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

在某些情况下,将其分配给false,null或undefined可能更安全,因此它被声明并不会抛出这种types的错误。

 foo = false 

请注意,在ECMAScript中, nullfalseundefined0NaN''都会计为false 。 只要确定你不使用!==运算符,而是在检查布尔值时,而不是使用!= ,而不需要进行身份检查(所以null== falsefalse == 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声明了一个variables,你不能删除它:

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

在犀牛:

 js> var x js> delete x false 

你也不能删除一些预定义的属性,如Math.PI

 js> delete Math.PI false 

有一些奇怪的例外情况可以像任何语言一样delete ,如果你足够谨慎,你应该阅读:

 some_var = null; //or remove it.. delete some_var; 

TLDR:简单定义的variables(不含varletconst )可以用delete 。 如果你使用varletconst – 它们不能被删除,也不能用Reflect.deleteProperty delete

Chrome 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" 

FF Nightly 53.0a1显示相同的行为。

ECMAScript 2015提供Reflect API。 可以使用Reflect.deleteProperty()删除对象属性:

 Reflect.deleteProperty(myObject, 'myProp'); // it is equivalent to: delete myObject.myProp; delete myObject['myProp']; 

删除全局window对象的属性:

 Reflect.deleteProperty(window, 'some_var'); 

在某些情况下,属性不能被删除(当属性不可configuration时),然后这个函数返回false (以及删除操作符 )。 在其他情况下返回true

 Object.defineProperty(window, 'some_var', { configurable: false, writable: true, enumerable: true, value: 'some_val' }); var frozen = Object.freeze({ myProperty: 'myValue' }); var regular = { myProperty: 'myValue' }; var blank = {}; console.log(Reflect.deleteProperty(window, 'some_var')); // false console.log(window.some_var); // some_var console.log(Reflect.deleteProperty(frozen, 'myProperty')); // false console.log(frozen.myProperty); // myValue console.log(Reflect.deleteProperty(regular, 'myProperty')); // true console.log(regular.myProperty); // undefined console.log(Reflect.deleteProperty(blank, 'notExistingProperty')); // true console.log(blank.notExistingProperty); // undefined 

在严格模式下运行时, deleteProperty函数与delete操作符有区别:

 'use strict' var frozen = Object.freeze({ myProperty: 'myValue' }); Reflect.deleteProperty(frozen, 'myProperty'); // false delete frozen.myProperty; // TypeError: property "myProperty" is non-configurable and can't be deleted 

除了每个人写的东西,还要注意delete返回布尔值。 它可以告诉你,删除是否成功。

更新:

在最新的Chrome上进行testing,一切都可以删除。 delete函数对于以下所有方法都返回true ,并实际删除它们:

 implicit_global = 1; window.explicit_global = 1; function_set = function() {}; function function_dec() { }; var declared_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 object.property delete object['property'] 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete

根据这个问题你需要以下一个

 delete some_var; delete window.some_var; delete window['some_var']; 

如果您在首次使用时声明(使用var x;),则无法删除variables。 但是,如果variablesx首先出现在没有声明的脚本中,那么可以使用delete操作符(delete x;)并将variables删除,这非常类似于删除数组元素或删除对象的属性。

与简单属性相比,variables具有[[Configurable]]属性,意味着不可能通过删除操作删除variables。 然而,这个规则不会影响到一个执行上下文。 这是eval上下文:没有为variables设置[[Configurable]]属性。