如何取消设置JavaScript变量?

如何取消设置JavaScript变量?,javascript,global-variables,undefined,variable-declaration,unset,Javascript,Global Variables,Undefined,Variable Declaration,Unset,我在JavaScript中有一个全局变量(实际上是一个窗口属性,但我认为这并不重要),它已经由以前的脚本填充,但我不希望以后运行的另一个脚本看到它的值,甚至不希望它被定义 我把some\u var=undefined放进去,它是为了测试some\u var==“undefined”的类型,但我真的认为这不是正确的方法 你怎么看?编辑了更新,以澄清各种选项(取决于你想要的意图) 有关详细信息,请参见@noah的答案 //Option A.) set to null some_var = null;

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

我把
some\u var=undefined
放进去,它是为了测试some\u var==“undefined”的
类型,但我真的认为这不是正确的方法

你怎么看?

编辑了更新,以澄清各种选项(取决于你想要的意图)

有关详细信息,请参见@noah的答案

//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;
参考资料:


如果隐式声明变量而不使用
var
,正确的方法是使用
delete foo

但是,在删除它之后,如果您尝试在诸如添加之类的操作中使用它,将抛出一个
ReferenceError
,因为您无法将字符串添加到未声明、未定义的标识符中。例如:

x = 5;
delete x
alert('foo' + x )
// ReferenceError: x is not defined
在某些情况下,将其指定为false、null或undefined可能更安全,这样它就被声明了,不会抛出这种类型的错误

foo = false
请注意,在ECMAScript中,
null
false
undefined
0
NaN
'
都将计算为
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
})();
在Rhino中:

js> var x
js> delete x
false
也不能删除一些预定义属性,如
Math.PI

js> delete Math.PI
false
与任何语言一样,
delete
也有一些奇怪的例外,如果你足够在意,你应该阅读:


@scunlife的答案是可行的,但从技术上讲应该是可行的

delete window.some_var; 
当目标不是对象属性时,delete应该是no-op。e、 g

(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会变得更复杂,因为它只从目标对象中删除属性,而不从原型中删除属性。e、 g

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.
所以要小心


编辑:我的答案是(见最后的“误解”)。该链接解释了所有血淋淋的细节,但总结是浏览器之间可能存在很大的差异,这取决于您要从中删除的对象<代码>删除对象。只要
对象!==窗口
。我仍然不会用它来删除用
var
声明的变量,尽管在正确的情况下可以这样做。

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

(1) 如果它是使用
var
创建的,则无法删除

例如:

var g_a=1//使用var创建,g_a是一个变量
删除g_a//返回错误
控制台日志(g_a)//g_a仍然是1
(2) 如果创建时未使用
var
,则可以将其删除

g_b=1//不使用var创建,g_b是一个属性
删除g_b//返回真值
控制台日志(g_b)//错误,未定义g_b
技术说明 1.使用
var
在这种情况下,引用“代码> GyA var >代码>的函数执行上下文(尽管当您考虑<代码>让/<代码>时,它可能会变得更复杂一些),或者在“全局”的情况下。代码将VariableEnvironment附加到全局对象(通常是
窗口

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

2.不使用
var
当试图在不使用
var
关键字的情况下为名称赋值时,Javascript会尝试在ECMAScript规范所称的“”中定位命名引用,主要区别在于LexicalEnvironment是嵌套的,也就是说,LexicalEnvironment有一个父级(ECMAScript规范所称的“外部环境引用”)当Javascript无法在LexicalEnvironment中找到引用时,它会在父LexicalEnvironment中查找(如和中所述)。顶级词典环境是“”,它绑定到全局对象,因为它的引用是全局对象的属性。因此,如果您试图访问当前作用域或任何外部作用域中未使用
var
关键字声明的名称,Javascript最终将获取
窗口
对象的属性作为该引用。如前所述,可以删除对象上的属性

笔记
  • 重要的是要记住,
    var
    声明是“被提升的”——即,它们总是被认为发生在它们所处的范围的开始处——尽管不是可以在
    var
    语句中完成的值初始化——它们被放在原来的位置。因此,在以下代码中,
    a
    是来自VariableEnvironment的引用,而不是
    窗口
    属性,其值将在代码末尾为
    10

    函数测试(){a=5;var a=10;}
    
  • 上述讨论是在未启用“严格模式”时进行的。查找规则a
    implicit_global = 1;
    delete implicit_global; // true
    
    window.explicit_global = 1;
    delete explicit_global; // true
    
    const _object = {property: 1};
    delete _object.property; // true
    
    function_set = function() {};
    delete function_set; // true
    
    function function_declaration() {};
    delete function_declaration; // false
    
    (function () {
        var _var = 1;
        console.log(delete _var); // false
        console.log(_var); // 1
    })()
    
    (function () {
        let _let = 1;
        console.log(delete _let); // false
        console.log(_let); // 1
    })()
    
    (function () {
        const _const = 1;
        console.log(delete _const); // false
        console.log(_const); // 1
    })()
    
    implicit_global = 1;
    window.explicit_global = 1;
    function_set = function() {};
    function function_dec() { };
    var declared_variable = 1;
    
    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']
    
    delete some_var;
    delete window.some_var;
    delete window['some_var'];
    
    Reflect.deleteProperty(myObject, 'myProp');
    // it is equivalent to:
    delete myObject.myProp;
    delete myObject['myProp'];
    
    Reflect.deleteProperty(window, 'some_var');
    
    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
    
    '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
    
    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"
    
    foo = null;
    if(foo === null) or if(foo !== null)
    
    x = null;