如何取消设置 JavaScript 变量?
我在 JavaScript 中有一个全局变量(实际上是一个 window
属性,但我认为这并不重要),该变量已由先前的脚本填充,但我不希望稍后运行另一个脚本看看它的价值或者它甚至被定义了。
我已经输入了 some_var = undefined
,它的目的是为了测试 typeof some_var == "undefined"
但我真的不认为这是正确的方法。
你怎么认为?
I have a global variable in JavaScript (actually a window
property, but I don't think it matters) which was already populated by a previous script, but I don't want another script that will run later to see its value or that it was even defined.
I've put some_var = undefined
and it works for the purpose of testing typeof some_var == "undefined"
but I really do not think it's the right way to go about it.
What do you think?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
delete
运算符从对象中删除属性。它无法删除变量。所以问题的答案取决于全局变量或属性是如何定义的。(1) 如果是用
var
创建的,则无法删除。例如:
(2) 如果创建时没有
var
,则可以将其删除。技术说明
1. 使用
var
在这种情况下,引用
g_a
是在 ECMAScript 规范中所谓的“VariableEnvironment" 附加到当前范围 - 这可能是函数执行上下文在函数内部使用var
的情况(尽管当您考虑let
时可能会变得更复杂一些),或者在“全局”代码的情况下,VariableEnvironment 附加到全局对象(通常是窗口
)。VariableEnvironment 中的引用通常不可删除 - ECMAScript 10.5 详细解释了这一点,但足以说明,除非您的代码在
eval
上下文中执行(大多数基于浏览器的开发控制台使用该上下文),否则变量用var
声明的不能被删除。2. 不使用
var
当尝试在不使用
var
关键字的情况下为名称分配值时,JavaScript 会尝试在 ECMAScript 规范中所谓的“LexicalEnvironment”,以及主要区别是 LexicalEnvironment 是嵌套的 - 即 LexicalEnvironment 有一个父级(ECMAScript 规范称之为“外部环境引用”),并且当 JavaScript 无法在LexicalEnvironment,它在父LexicalEnvironment中查找(详见10.3.1 和 10.2.2.1)。顶级 LexicalEnvironment 是“ 全局环境”,并且它绑定到全局对象,因为它的引用是全局对象的属性。因此,如果您尝试访问当前作用域或任何外部作用域中未使用var
关键字声明的名称,JavaScript 最终将获取window
对象的属性作为那个参考。正如我们之前所了解的,对象的属性可以被删除。注意
重要的是要记住
var
声明是“提升的” - 即它们总是被认为发生在它们所在范围的开头 - 尽管不是可能的值初始化在var
语句中完成 - 保留在原来的位置。因此,在下面的代码中,a
是来自 VariableEnvironment 的引用,而不是window
属性,其值将为10代码> 代码末尾:
上面讨论的是未启用“严格模式”时的情况。使用“严格模式”时,查找规则有点不同,在没有“严格模式”的情况下解析为窗口属性的词法引用将在“严格模式”下引发“未声明的变量”错误。我不太明白这是在哪里指定的,但它是浏览器的行为方式。
The
delete
operator removes a property from an object. It cannot remove a variable. So the answer to the question depends on how the global variable or property is defined.(1) If it is created with
var
, it cannot be deleted.For example:
(2) If it is created without
var
, it can be deleted.Technical Explanation
1. Using
var
In this case the reference
g_a
is created in what the ECMAScript spec calls "VariableEnvironment" that is attached to the current scope - this may be the a function execution context in the case of usingvar
inside a function (though it may be get a little more complicated when you considerlet
) or in the case of "global" code the VariableEnvironment is attached to the global object (oftenwindow
).References in the VariableEnvironment are not normally deletable - the process detailed in ECMAScript 10.5 explains this in detail, but suffice it to say that unless your code is executed in an
eval
context (which most browser-based development consoles use), then variables declared withvar
cannot be deleted.2. Without Using
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 avar
keyword in the current scope or any outer scopes, JavaScript will eventually fetch a property of thewindow
object to serve as that reference. As we've learned before, properties on objects can be deleted.Notes
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 avar
statement - that is left where it is. So in the following code,a
is a reference from the VariableEnvironment and not thewindow
property and its value will be10
at the end of the code: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.
scunliffe的答案会起作用,但从技术上讲应该可以 当目标不是对象属性时, be
delete 应该是无操作。例如,
但是由于全局变量实际上是 window 对象的成员,因此它可以工作。
当涉及原型链时,使用删除会变得更加复杂,因为它只从目标对象中删除属性,而不是原型。例如,
所以要小心。
注意:我的回答有些不准确(请参阅最后的“误解”)。该链接解释了所有血淋淋的细节,但总结是,浏览器之间可能存在很大差异,具体取决于您要从中删除的对象。只要
object !== window
,delete object.someProp
通常应该是安全的。我仍然不会使用它来删除用var
声明的变量,尽管在适当的情况下您可以。scunliffe's answer will work, but technically it ought to be
delete is supposed to be a no-op when the target isn't an object property. e.g.,
But since global variables are actually members of the window object, it works.
When prototype chains are involved, using delete gets more complex because it only removes the property from the target object, and not the prototype. e.g.,
So be careful.
Note: My answer is somewhat inaccurate (see "Misconceptions" at the end). The link explains all the gory details, but the summary is that there can be big differences between browsers and depending on the object you are deleting from.
delete object.someProp
should generally be safe as long asobject !== window
. I still wouldn't use it to delete variables declared withvar
although you can under the right circumstances.如果您在没有
var
的情况下隐式声明变量,正确的方法是使用delete foo
。但是,在删除它之后,如果您尝试在添加等操作中使用它,则会抛出
ReferenceError
,因为您无法将字符串添加到未声明、未定义的标识符。示例:在某些情况下,将其分配给 false、null 或 undefined 可能会更安全,因此它被声明并且不会引发此类错误。
请注意,在 ECMAScript 中
null
、false
、undefined
、0
、NaN
或''
将全部计算为false
。只需确保在对布尔值进行类型检查时不使用!==
运算符,而是使用!=
并且您不希望进行身份检查(因此null
code> 将== false
和false == undefined
)。另请注意,
delete
不会“删除”引用,而只是直接删除对象上的属性,例如:如果您使用
var
声明了变量,则无法删除它:在Rhino中:
您也不能删除一些预定义的属性,例如
Math.PI
:与任何语言一样,
删除
有一些奇怪的例外,如果您足够关心,您应该阅读:If you are implicitly declaring the variable without
var
, the proper way would be to usedelete foo
.However after you delete it, if you try to use this in an operation such as addition a
ReferenceError
will be thrown because you can't add a string to an undeclared, undefined identifier. Example:It may be safer in some situations to assign it to false, null, or undefined so it's declared and won't throw this type of error.
Note that in ECMAScript
null
,false
,undefined
,0
,NaN
, or''
would all evaluate tofalse
. Just make sure you dont use the!==
operator but instead!=
when type checking for booleans and you don't want identity checking (sonull
would== false
andfalse == undefined
).Also note that
delete
doesn't "delete" references but just properties directly on the object, e.g.:If you have declared a variable with
var
you can't delete it:In Rhino:
Nor can you delete some predefined properties like
Math.PI
:There are some odd exceptions to
delete
as with any language, if you care enough you should read:有关完整详细信息,请参阅 noah 的回答
参考文献:
MDN 删除 API
在严格模式下删除不合格的变量名称时出现 MDN 语法错误
See noah's answer for full details
References:
MDN delete API
MDN SyntaxError when deleting an unqualified variable name in strict mode
TLDR:简单定义的变量(没有
var
、let
、const
)可以用delete
删除。如果您使用var
、let
、const
- 它们既不能用delete
也不能用删除Reflect.deleteProperty
。Chrome 55:
Firefox Nightly 53.0a1 显示相同的行为。
TLDR: simple defined variables (without
var
,let
,const
) could be deleted withdelete
. If you usevar
,let
,const
- they could not be deleted neither withdelete
nor withReflect.deleteProperty
.Chrome 55:
Firefox Nightly 53.0a1 shows the same behaviour.
⚠️ 接受的答案(和其他答案)已经过时了!
TL;DR
delete
不会删除变量。(仅用于从对象中删除属性。)
“取消设置”的正确方法是将变量简单地设置为
null
。 (来源)< br>(这使得 JavaScript 的自动进程能够删除
来自内存的变量。)
示例:
⚠️ The accepted answer (and others) are outdated!
TL;DR
delete
does not remove variables.(It's only for removing a property from an object.)
The correct way to "unset" is to simply set the variable to
null
. (source)(This enables JavaScript's automatic processes to remove the
variable from memory.)
Example:
????
More info:
Use of the
delete
operator on a variable is deprecated since 2012, when all browsers implemented (automatic) mark-and-sweep garbage-collection. The process works by automatically determining when objects/variables become "unreachable" (deciding whether or not the code still requires them).With JavaScript, in all modern browsers:
The
delete
operator is only used to remove a property from an object;it does not remove variables.
When using strict mode (
'use strict';
, as opposed to regular/"sloppy mode") an attempt to delete a variable will throw an error and is not allowed. Normal variables in JavaScript can't be deleted using thedelete
operator (source) (or any other way, as of 2021)....alas, the only solution:
Freeing the contents of a variable
To free the contents of a variable, you can simply set it to
null
:(source)
Further Reading:
ECMAScript 2015 提供了 Reflect API。可以使用 Reflect 删除对象属性.deleteProperty():
删除全局
window
对象的属性:在某些情况下属性无法删除(当属性不可配置时),然后此函数返回
false
(以及删除运算符< /a>)。在其他情况下,它返回true
:在严格模式下运行时,
deleteProperty
函数和delete
运算符之间存在差异:ECMAScript 2015 offers Reflect API. It is possible to delete an object property with Reflect.deleteProperty():
To delete a property of the global
window
object:In some cases properties cannot be deleted (when the property is not configurable) and then this function returns
false
(as well as the delete operator). In other cases it returnstrue
:There is a difference between
deleteProperty
function anddelete
operator when run in strict mode:请注意,成功时
delete
返回true
。2021 年更新:在 Chrome 88 和 Firefox 84 上测试:
由于浏览器更新,此答案的先前编辑不再相关。
Note that
delete
returnstrue
when it was successful.Update 2021: tested on Chrome 88 and Firefox 84:
The previous edit of this answer is no longer relevant due to browser updates.
与简单属性相比,变量具有[[可配置]]属性,这意味着无法通过删除运算符删除变量。
然而,有一种执行上下文不受此规则的影响。这是eval上下文:没有为变量设置[[Configurable]]属性。
Variables, in contrast to simple properties, have the attribute [[Configurable]], meaning impossibility to remove a variable via the delete operator.
However, there is one execution context in which this rule does not affect. It is the eval context: there the [[Configurable]] attribute is not set for variables.
删除运算符从对象中删除属性。
https://developer.mozilla.org/en-US /docs/Web/JavaScript/Reference/Operators/delete
根据问题,您需要以下之一
The delete operator removes a property from an object.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete
According to the question you need one of followings
如果在首次使用时声明了变量(使用
var x;
),则无法删除该变量。但是,如果您的变量
x
首次出现在没有声明的脚本中,那么您可以使用delete
运算符 (delete x;
) 和您的变量变量将被删除,与删除数组的元素或删除对象的属性非常相似。You cannot delete a variable if you declared it (with
var x;
) at the time of first use.However, if your variable
x
first appeared in the script without a declaration, then you can use thedelete
operator (delete x;
) and your variable will be deleted, very similar to deleting an element of an array or deleting a property of an object.我有点困惑。如果您想要的只是变量值不传递给另一个脚本,则无需从作用域中删除该变量。
只需使变量无效,然后显式检查它是否为空。为什么要经历从作用域中删除变量的麻烦呢?这能达到什么目的,而无效则不能呢?
I am bit confused. If all you want is for a variables value to not pass to another script then there isn't any need to delete the variable from the scope.
Simply nullify the variable and then explicit check if it is or is not null. Why go through the trouble of deleting the variable from the scope? What purpose does this serve that nullifying can not?