Javascript中variables声明语法之间的区别(包括全局variables)?
声明一个variables是否有区别:
var a=0; //1
…这条路:
a=0; //2
…要么:
window.a=0; //3
在全球范围内?
是的,有一些差异,但实际上它们通常不是很大。
还有第四种方法,ES2015(ES6)还有两种。 我在最后添加了第四种方法,但是在#1之后插入了ES2015方法(您会看到为什么),所以我们有:
var a = 0; // 1 let a = 0; // 1.1 (new with ES2015) const a = 0; // 1.2 (new with ES2015) a = 0; // 2 window.a = 0; // 3 this.a = 0; // 4
那些陈述解释
#1 var a = 0;
这创build了一个全局variables,它也是全局对象的一个属性,我们通过浏览器(或通过全局范围,非严格代码)访问这个全局对象 。 与其他一些属性不同,该属性不能通过删除来delete
。
在规范方面,它会在全局环境的对象环境logging上创build一个标识符绑定 。 这使得它成为全局对象的一个属性,因为全局对象是全局环境的对象环境logging的标识符绑定的地方。 这就是为什么该属性是不可删除的:它不只是一个简单的属性,它是一个标识符绑定。
绑定(variables)在第一行代码运行之前定义(请参阅下面的“当var
发生时”)。
请注意,在IE8和更早版本上,在window
上创build的属性不是可枚举的 (不会显示在for..in
语句中)。 在IE9,Chrome,Firefox和Opera中,它是可枚举的。
#1.1 let a = 0;
这会创build一个不是全局对象属性的全局variables。 这是ES2015的新事物。
在规范方面,它为全局环境的声明性环境logging创build一个标识符绑定,而不是对象环境logging。 全局环境是独一无二的,它有一个拆分的环境logging,一个用于全局对象( 对象环境logging)的所有旧东西,另一个用于所有新东西( let
, const
和由class
创build的函数)不要放在全局对象上。
绑定是在其封闭块中的任何分步代码被执行之前创build的 (在这种情况下,在任何全局代码运行之前),但是在逐步执行到达let
语句之前,不能以任何方式访问它。 一旦执行到达let
语句,variables就可以访问。 (请参阅下面的“当let
和const
发生时”。)
#1.2 const a = 0;
创build一个全局常量,它不是全局对象的一个属性。
const
是完全像let
除了你必须提供一个初始= value
( = value
部分),并且你不能在创build它之后改变这个常量的值。 在封面之下,它就像是let
标记绑定的标志,说它的价值不能改变。 使用const
为你做三件事:
- 如果尝试分配给常量,则会导致分析时错误。
- 为其他程序员logging其不变的性质。
- 让JavaScript引擎在不会改变的基础上进行优化。
#2 a = 0;
这将隐式地在全局对象上创build一个属性。 由于这是一个正常的属性,你可以删除它。 我build议不要这样做,以后任何人阅读你的代码可能都不清楚。
有趣的是,在IE8和更早的版本中,创build的属性不是枚举的 (不会在for..in
语句中显示)。 这很奇怪,特别是下面的#3。
#3 window.a = 0;
这将使用引用全局对象的window
全局(在浏览器上;某些非浏览器环境具有等效的全局variables,如NodeJS上的全局对象),在全局对象上显式创build一个属性。 由于这是一个正常的属性,你可以删除它。
这个属性是可枚举的,在IE8和更早的版本上,以及我尝试过的每个其他浏览器上。
#4 this.a = 0;
完全像#3,除了我们通过this
引用全局对象而不是全局window
。 这在严格模式下不起作用,因为在严格模式的全局代码中,没有引用全局对象(它的值是undefined
)。
删除属性
我的意思是“删除”或“删除” a
? 确切地说:通过delete
关键字delete
(全部)属性:
window.a = 0; display("'a' in window? " + ('a' in window)); // displays "true" delete window.a; display("'a' in window? " + ('a' in window)); // displays "false"
delete
完全删除对象的属性。 您无法通过var
通过间接向window
添加属性来完成此操作, delete
被默认忽略或引发exception(取决于JavaScript实现以及您是否处于严格模式)。
警告 :IE8再次(大概是早些时候和IE9-IE11中的“兼容性”模式):即使你被允许,也不会让你删除window
对象的属性。 更糟糕的是,当您尝试(在IE8和其他浏览器中尝试此实验)时会引发exception 。 所以当从window
对象删除时,你必须是防御性的:
try { delete window.prop; } catch (e) { window.prop = undefined; }
这会尝试删除该属性,如果抛出exception,则会执行下一个最佳操作,并将该属性设置为undefined
。
这只适用于window
对象,并且只有(据我所知)IE8及更早的版本(或IE9-IE11中断的“兼容性”模式)。 其他浏览器可以删除window
属性,但要遵守上述规则。
当var
发生
通过var
语句定义的variables是在执行上下文中的任何一步一步的代码运行之前创build的,因此该属性存在于var
语句之前 。
这可能会让人困惑,所以让我们来看看:
display("foo in window? " + ('foo' in window)); // displays "true" display("window.foo = " + window.foo); // displays "undefined" display("bar in window? " + ('bar' in window)); // displays "false" display("window.bar = " + window.bar); // displays "undefined" var foo = "f"; bar = "b"; display("foo in window? " + ('foo' in window)); // displays "true" display("window.foo = " + window.foo); // displays "f" display("bar in window? " + ('bar' in window)); // displays "true" display("window.bar = " + window.bar); // displays "b"
现场示例:
display("foo in window? " + ('foo' in window)); // displays "true" display("window.foo = " + window.foo); // displays "undefined" display("bar in window? " + ('bar' in window)); // displays "false" display("window.bar = " + window.bar); // displays "undefined" var foo = "f"; bar = "b"; display("foo in window? " + ('foo' in window)); // displays "true" display("window.foo = " + window.foo); // displays "f" display("bar in window? " + ('bar' in window)); // displays "true" display("window.bar = " + window.bar); // displays "b" function display(msg) { var p = document.createElement('p'); p.innerHTML = msg; document.body.appendChild(p); }
保持简单:
a = 0
上面的代码给出了一个全局范围variables
var a = 0;
这段代码将给出一个在当前范围内使用的variables,并在其下面
window.a = 0;
这通常与全局variables相同。
<title>Index.html</title> <script> var varDeclaration = true; noVarDeclaration = true; window.hungOnWindow = true; document.hungOnDocument = true; </script> <script src="external.js"></script> /* external.js */ console.info(varDeclaration == true); // could be .log, alert etc // returns false in IE8 console.info(noVarDeclaration == true); // could be .log, alert etc // returns false in IE8 console.info(window.hungOnWindow == true); // could be .log, alert etc // returns true in IE8 console.info(document.hungOnDocument == true); // could be .log, alert etc // returns ??? in IE8 (untested!) *I personally find this more clugy than hanging off window obj
有没有一个全球性的对象,所有的variables都被默认挂起? 例如:'globals.noVar声明'
基于TJ Crowder的优秀回答:( 题外话:避免杂乱的window
)
这是他的想法的一个例子:
HTML
<!DOCTYPE html> <html> <head> <script type="text/javascript" src="init.js"></script> <script type="text/javascript"> MYLIBRARY.init(["firstValue", 2, "thirdValue"]); </script> <script src="script.js"></script> </head> <body> <h1>Hello !</h1> </body> </html>
init.js (基于这个答案 )
var MYLIBRARY = MYLIBRARY || (function(){ var _args = {}; // private return { init : function(Args) { _args = Args; // some other initialising }, helloWorld : function(i) { return _args[i]; } }; }());
的script.js
// Here you can use the values defined in the html as if it were a global variable var a = "Hello World " + MYLIBRARY.helloWorld(2); alert(a);
这是plnkr 。 希望它有帮助!
在全球范围内,没有语义上的差异。
但是,您应该避免a=0
因为您将值设置为未声明的variables。
也可以使用闭包来避免编辑全局范围
(function() { // do stuff locally // Hoist something to global scope window.someGlobal = someLocal }());
在绝对必要的情况下,始终使用closures,并始终提升到全球范围。 无论如何,您应该使用asynchronous事件处理来处理大部分通信。
作为@AvianMoncellor提到有一个IE浏览器的错误与var a = foo
只声明全局的文件范围。 这是IE的臭名昭着的破译员的问题。 这个bug听起来很熟悉,所以可能是真的。
所以坚持window.globalName = someLocalpointer