如何取消设置JavaScript变量?

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

我已经把some_var = undefined ,它用于测试typeof some_var == "undefined"的目的,但我真的不认为这是正确的方式去做。

你怎么看?


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

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

(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时更复杂),或者在全局代码的情况下,VariableEnvironment被附加到全局对象(通常是window )。

变量环境中的引用通常不是可删除的--ECMAScript 10.5中详细描述的过程详细解释了这一点,但可以这么说,除非您的代码在eval上下文中执行(大多数基于浏览器的开发控制台都使用该代码),然后使用var无法删除。

2.没有使用var

当试图在不使用var关键字的情况下为某个名称赋值时,Javascript会尝试在ECMAScript规范所称的“LexicalEnvironment”中定位指定的引用,主要区别在于LexicalEvironments是嵌套的 - 即LexicalEnvironment具有父级ECMAScript规范称为“外部环境参考”)以及Javscript无法在LexicalEenvironment中找到引用时,它会在父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; }

  • 以上讨论是当“严格模式”未启用时。 当使用“严格模式”时,查找规则有点不同,如果没有“严格模式”会在“严格模式”下引发“未声明的变量”错误,那么解析为窗口属性的词法引用也会有所不同。 我真的不明白这是在哪里指定的,但它的浏览器行为如何。


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

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

    当涉及原型链时,使用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因为您无法将字符串添加到未声明的未定义标识符。 例:

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

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

    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声明了一个变量,你不能删除它:

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

    在犀牛:

    js> var x
    js> delete x
    false
    

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

    js> delete Math.PI
    false
    

    与任何语言一样, delete一些奇怪的例外情况,如果您足够关心,您应该阅读:

  • https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Operators/Special_Operators/delete_Operator
  • http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf
  • 链接地址: http://www.djcxy.com/p/27223.html

    上一篇: How to unset a JavaScript variable?

    下一篇: How do I remove a property from a JavaScript object?