【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
我在JavaScript中有一个全局变量(实际上是一个window
属性,但我认为这并不重要),该变量已经由先前的脚本填充,但是我不希望另一个稍后运行的脚本来查看其值或甚至定义。
我已经放了some_var = undefined
,它可以用于测试typeof some_var == "undefined"
但是我真的不认为这是正确的方法。
你怎么看?
#1楼
some_var = null;
//or remove it..
delete some_var;
#2楼
如果您隐式声明不带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
})();
在犀牛中:
js> var x
js> delete x
false
您也不能删除一些预定义的属性,例如Math.PI
:
js> delete Math.PI
false
与任何语言一样,有一些奇怪的例外要delete
,如果您足够关心,则应阅读:
- https://developer.mozilla.org/zh-CN/Core_JavaScript_1.5_Reference/Operators/Special_Operators/delete_Operator
- http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf
#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.1和10.2.2.1中所述 )。 顶级LexicalEnvironment是“ 全局环境 ”,它绑定到全局对象,因为它的引用是全局对象的属性。 因此,如果您尝试访问在当前范围或任何外部范围中未使用var
关键字声明的名称,则Javascript最终将获取window
对象的属性以用作该引用。 正如我们之前所了解的,可以删除对象的属性。
笔记
重要的是要记住
var
声明是“悬挂的”-即始终认为它们已在它们所在范围的开头发生-尽管不是在var
语句中可能完成的值初始化-留在了它是。 因此,在以下代码中,a
是VariableEnvironment的引用,而不是window
属性的引用,在代码末尾,其值为10
:function test() { a = 5; var a = 10; }
以上讨论是在未启用“严格模式”的情况下。 使用“严格模式”时,查找规则略有不同,如果没有“严格模式”就可以解析为窗口属性的词法引用将在“严格模式”下引发“未声明变量”错误。 我不太了解在哪里指定它,但是它在浏览器中的表现如何。
#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
来源:oschina
链接:https://my.oschina.net/u/3797416/blog/3154120