如何取消设置JavaScript变量? [英] How to unset a JavaScript variable?

查看:104
本文介绍了如何取消设置JavaScript变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我已将 some_var = undefined ,它可用于测试 typeof some_var ==undefined,但我真的认为这不是正确的解决方法。



你认为什么? 我知道这是一个旧的线程,但选择的答案对我来说还不够清楚。



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



(1)如果它是用var创建的,它不能被删除。



例如:

  var g_a = 1; //用var创建,g_a是一个变量
delete g_a; //返回false
console.log(g_a); // g_a仍然是1

(2)如果没有创建var,它可以被删除。

  g_b = 1; //创建不带var,g_b是一个属性
delete g_b; //返回true
console.log(g_b); //错误,未定义g_b



技术解释



1。使用 var



在这种情况下,参考 g_a 是创建于ECMAScript规范所称的 VariableEnvironment 这是附加到当前范围 - 这可能是一个函数执行上下文的情况下,在函数内使用 var (虽然它可能会稍微复杂一点,当你考虑 let ),或者在全局代码的情况下,将 VariableEnvironment 附加到全局对象(通常 window )。


$ b VariableEnvironment 中的引用通常不可删除 - ECMAScript 10.5 详细解释了这一点,但足以说明,除非您的代码在<$ c $中执行c> eval context(大多数基于浏览器的开发控制台使用),然后使用 var 无法删除。



2。不使用 var



在不使用 var的情况下尝试为某个名称赋值关键字,Javascript尝试在ECMAScript规范所称的 LexicalEnvironment ,主要区别在于 LexicalEvironment 是嵌套的 - 即 具有父级ECMAScript规范调用外部环境引用),并且当Javscript无法在 LexicalEenvironment 中找到引用时,它会在父级 LexicalEnvironment 中查找(详见10.3.1 10.2.2.1 )。顶级 LexicalEnvironment 全球环境 ,并且这个绑定到全局对象的地方在于它的引用是全局对象的属性。因此,如果您尝试访问未在当前作用域或任何外部作用域中使用 var 关键字声明的名称,则Javascript将最终获取 window 对象作为参考。正如我们以前所了解的,对象的属性可以被删除。



注释




  1. 重要的是要记住 var 声明是悬挂的 - 即它们总是被认为是在它们所在的范围的开始处发生的 - 尽管不是可以在 var 语句中完成的值初始化 - 它仍然保留在原来的位置。因此,在下面的代码中, a 是来自 VariableEnvironment 的引用,而不是窗口属性及其值在代码末尾为 10



    函数测试(){a = 5; var a = 10; }


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



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?

解决方案

I know this is an old thread, but the selected answer isn't clear enough for me.

The point is 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:

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) If it is created without var, it can be deleted.

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

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 using var inside a function (though it may be get a little more complicated when you consider let) or in the case of "global" code the VariableEnvironment is attached to the global object (often window).

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 with var 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 LexicalEvironments are nested - that is a LexicalEnvironment has a parent (what the ECMAScript spec calls "outer environment reference") and when Javscript fails to locate the reference in a LexicalEenvironment, 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.

Notes

  1. 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; }

  2. 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.

这篇关于如何取消设置JavaScript变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆