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)的所有旧东西,另一个用于所有新东西( letconst和由class创build的函数)不要放在全局对象上。

绑定是在其封闭块中的任何分步代码被执行之前创build的 (在这种情况下,在任何全局代码运行之前),但是在逐步执行到达let语句之前,不能以任何方式访问它。 一旦执行到达let语句,variables就可以访问。 (请参阅下面的“当letconst发生时”。)


#1.2 const a = 0;

创build一个全局常量,它不是全局对象的一个​​属性。

const是完全像let除了你必须提供一个初始= value= value部分),并且你不能在创build它之后改变这个常量的值。 在封面之下,它就像是let标记绑定的标志,说它的价值不能改变。 使用const为你做三件事:

  1. 如果尝试分配给常量,则会导致分析时错误。
  2. 为其他程序员logging其不变的性质。
  3. 让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