我在JavaScript中有一个全局变量(实际上是一个窗口属性,但我不认为这很重要),它已经由以前的脚本填充,但我不希望另一个脚本稍后运行,以查看它的值或它甚至被定义。
我已经把some_var = undefined,它用于测试类型的some_var ==“undefined”的目的,但我真的不认为这是正确的方法。
你怎么看?
我在JavaScript中有一个全局变量(实际上是一个窗口属性,但我不认为这很重要),它已经由以前的脚本填充,但我不希望另一个脚本稍后运行,以查看它的值或它甚至被定义。
我已经把some_var = undefined,它用于测试类型的some_var ==“undefined”的目的,但我真的不认为这是正确的方法。
你怎么看?
当前回答
斯坎利夫的答案是可行的,但从技术上讲,它应该是可行的
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
}());
但是由于全局变量实际上是窗口对象的成员,所以它是可行的。
当涉及原型链时,使用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.
所以要小心。
注:我的回答有些不准确(见末尾的“误解”)。这个链接解释了所有血腥的细节,但总的来说,不同的浏览器之间可能有很大的差异,这取决于你要删除的对象。删除对象。someProp通常应该是安全的,只要object !== window。我仍然不会使用它来删除用var声明的变量,尽管在适当的情况下可以这样做。
其他回答
如果你在第一次使用时声明了一个变量(使用var x;),你就不能删除它。 但是,如果你的变量x第一次出现在脚本中没有声明,那么你可以使用delete操作符(delete x;),你的变量将被删除,这与删除数组的元素或删除对象的属性非常相似。
delete操作符从对象中删除属性。
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'];
我有点糊涂了。如果你只是想让一个变量的值不传递给另一个脚本,那么就没有必要从作用域中删除这个变量。
只需使变量为空,然后显式检查它是否为空。为什么要麻烦地从作用域删除变量呢?这样做的目的是什么呢?
foo = null;
if(foo === null) or if(foo !== null)
ECMAScript 2015提供了Reflect API。可以使用Reflect.deleteProperty()删除对象属性:
Reflect.deleteProperty(myObject, 'myProp');
// it is equivalent to:
delete myObject.myProp;
delete myObject['myProp'];
删除全局窗口对象的一个属性:
Reflect.deleteProperty(window, 'some_var');
在某些情况下,属性不能被删除(当属性不可配置时),然后该函数返回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操作符从对象中删除属性。它不能删除变量。所以这个问题的答案取决于全局变量或属性是如何定义的。
(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附加到全局对象(通常是窗口)。
VariableEnvironment中的引用通常是不可删除的——ECMAScript 10.5中详细解释了这一点,但只需说明,除非您的代码在eval上下文中执行(大多数基于浏览器的开发控制台使用),否则使用var声明的变量是不能删除的。
2. 不使用var
When trying to assign a value to a name without using the var keyword, JavaScript tries to locate the named reference in what the ECMAScript spec calls "LexicalEnvironment", and the main difference is that LexicalEnvironments are nested - that is a LexicalEnvironment has a parent (what the ECMAScript spec calls "outer environment reference") and when JavaScript fails to locate the reference in a LexicalEnvironment, it looks in the parent LexicalEnvironment (as detailed in 10.3.1 and 10.2.2.1). The top level LexicalEnvironment is the "global environment", and that is bound to the global object in that its references are the global object's properties. So if you try to access a name that was not declared using a var keyword in the current scope or any outer scopes, JavaScript will eventually fetch a property of the window object to serve as that reference. As we've learned before, properties on objects can be deleted.
笔记
It is important to remember that var declarations are "hoisted" - i.e. they are always considered to have happened in the beginning of the scope that they are in - though not the value initialization that may be done in a var statement - that is left where it is. So in the following code, a is a reference from the VariableEnvironment and not the window property and its value will be 10 at the end of the code: function test() { a = 5; var a = 10; } The above discussion is when "strict mode" is not enabled. Lookup rules are a bit different when using "strict mode" and lexical references that would have resolved to window properties without "strict mode" will raise "undeclared variable" errors under "strict mode". I didn't really understand where this is specified, but its how browsers behave.