var关键字的用途是什么以及何时使用(或省略)?
注意 :这个问题是从ECMAScript版本3或5的angular度提出的。在ECMAScript 6版本中引入新function可能会使答案过时。
Javascript中var
关键字的function究竟是什么,以及它们之间有什么区别:
var someNumber = 2; var someFunction = function() { doSomething; } var someObject = { } var someObject.someProperty = 5;
和:
someNumber = 2; someFunction = function() { doSomething; } someObject = { } someObject.someProperty = 5;
你什么时候可以使用一个,为什么?它有什么作用?
如果你在全球范围内,那么没有什么区别。
如果你在一个函数中,那么var
将创build一个局部variables,“no var”将查找范围链,直到它findvariables或者命中全局范围(在这个点上它将创build它):
// These are both globals var foo = 1; bar = 2; function() { var foo = 1; // Local bar = 2; // Global // Execute an anonymous function (function() { var wibble = 1; // Local foo = 2; // Inherits from scope above (creating a closure) moo = 3; // Global }()) }
如果你没有做任务,那么你需要使用var
:
var x; // Declare x
有一个区别 。
var x = 1
在当前作用域(又名执行上下文)中声明variables x
。 如果声明出现在一个函数中 – 声明一个局部variables; 如果它在全局范围内 – 则声明一个全局variables。
另一方面, x = 1
只是一个财产分配。 它首先试图解决范围链的x
。 如果它在该范围链中的任何地方find它,它将执行分配; 如果它没有findx
,那么它只会在全局对象 (这是作用域链中的顶级对象) 上创buildx
属性 。
现在注意到它没有声明一个全局variables,它创build了一个全局属性。
两者之间的差异是微妙的,可能会混淆,除非你明白, variables声明也创build属性 (只在一个variables对象),并且在Javascript(以及ECMAScript)的每个属性都有一些标志,描述它们的属性 – ReadOnly,DontEnum和DontDelete。
由于variables声明用DontDelete标志创build属性,所以var x = 1
和x = 1
(当在全局范围中执行时)之间的区别在于前一个variables声明 – 创build了DontDelete'able属性,而后者不。 因此,通过这个隐式赋值创build的属性可以从全局对象中删除,而前一个 – 通过variables声明创build的属性 – 不能被删除。
但是这当然只是理论, 实际上由于各种实现(比如来自IE的)的缺陷, 两者之间还是会有更多的差异 。
希望这一切都有道理:)
[2010/12/16更新]
在ES5(ECMAScript 5;最近标准化,第五版的语言)中,有一个所谓的“严格模式” – 一种select性的语言模式,稍微改变未申报的任务的行为。 在严格模式下,分配给未声明的标识符是一个ReferenceError 。 其理由是为了避免意外分配,防止产生不希望的全球性质。 一些较新的浏览器已经开始支持严格模式。 例如,看我的compat表 。
说“ 地方与全球 ”的区别并不完全准确。
把它当作“ 本地和最近 ”的区别可能会更好。 最近的可以肯定是全球性的,但事实并非总是如此。
/* global scope */ var local = true; var global = true; function outer() { /* local scope */ var local = true; var global = false; /* nearest scope = outer */ local = !global; function inner() { /* nearest scope = outer */ local = false; global = false; /* nearest scope = undefined */ /* defaults to defining a global */ public = global; } }
当Javascript在浏览器中执行时,所有的代码都被一个with语句所包围,如下所示:
with (window) { //Your code }
更多信息with
– MDN
由于var
在当前范围中声明了一个variables,所以在窗口内声明var
并且根本不声明它是没有区别的。
当你不是直接在窗口内部,例如在一个函数内部或者在一个块内,差异会出现。
使用var
可以隐藏具有相同名称的外部variables。 这样你就可以模拟一个“私有”variables,但这是另一个话题。
经验法则是总是使用var
,因为否则你冒着引入微妙的错误的风险。
编辑:我收到的批评后,我想强调以下几点:
-
var
在当前作用域中声明一个variables - 全球范围是
window
- 不使用
var
隐式地在全局范围(窗口)中声明var
- 使用
var
在全局范围(window)中声明variables与删除它相同。 - 使用
var
声明一个variables在与window不同的作用域中的作用与声明不带var
的variables是不一样的 - 总是声明
var
因为这是很好的做法
你应该总是使用var
关键字来声明variables。 为什么? 良好的编码实践本身应该是足够的理由,但是声明一个没有var
关键字的variables意味着它在全局范围内声明(像这样的variables称为“隐含的”全局variables)。 Douglas Crockford build议不要使用隐含的全局variables ,根据Apple JavaScript Coding Guidelines :
任何在不使用
var
关键字的情况下创build的variables都将在全局范围内创build,并且在函数返回时不会被垃圾回收(因为它不会超出范围),从而导致内存泄漏。
所以,总之,总是使用var
关键字来声明variables。
下面是一个非常好的例子,你可以从var
声明局部variables的方式来捕获它们:
<script> one(); function one() { for (i = 0;i < 10;i++) { two(); alert(i); } } function two() { i = 1; } </script>
( i
在循环的每一个迭代中重置,因为它不是在for
循环中本地声明,而是全局的),最终导致无限循环
我会说在大多数情况下使用var
更好。
局部variables总是比全局variables中的variables更快。
如果你不使用var
声明一个variables,variables将在全局范围内。
有关更多信息,您可以在Google中search“范围链JavaScript”。
另一个差别,如
var a = a || [] ; // works
而
a = a || [] ; // a is undefined error.
没有var
– 全局variables。
强烈build议总是使用var
语句,因为本地环境中的init全局variables – 是邪恶的。 但是,如果你需要这个肮脏的技巧,你应该在页面开始写评论:
/* global: varname1, varname2... */
使用var
总是一个好主意,防止variables混淆全局范围和variables彼此冲突,造成不必要的覆盖。
不要使用var
!
var
是声明variables的ES6之前的方法。 我们现在是在将来 ,你应该这样编码。
使用const
和let
95%的情况下应该使用const
。 它使得variables引用不能改变,因此数组,对象和DOM节点属性可以改变,并且可能是const
。
应该用于任何期望被重新分配的variables。 这包括在for循环中。 如果您在初始化之后编写varName =
,请使用let
。
正如大多数其他语言所预期的那样,两者都具有块级的范围。
这是我为你理解这个概念写的代码示例:
var foo = 5; bar = 2; fooba = 3; // Execute an anonymous function (function() { bar = 100; //overwrites global scope bar var foo = 4; //a new foo variable is created in this' function's scope var fooba = 900; //same as above document.write(foo); //prints 4 document.write(bar); //prints 100 document.write(fooba); //prints 900 })(); document.write('<br/>'); document.write('<br/>'); document.write(foo); //prints 5 document.write(bar); //prints 100 document.write(fooba); //prints 3
在代码里面,如果你使用一个variables而不使用var,那么会发生什么情况是var var_name被放置在全局范围内,例如:
someFunction() { var a = some_value; /*a has local scope and it cannot be accessed when this function is not active*/ b = a; /*here it places "var b" at top of script ie gives b global scope or uses already defined global variable b */ }
不使用“var”variables只能在设置值时进行定义。 例如:
my_var;
不能在全球范围或其他范围内工作 。 它应该像价值一样:
my_var = "value";
另一方面,你可以定义一个可爱的样子;
var my_var;
它的值是undefined
(它的值不是null
,它不等于null
有趣)。
正如有人试图学习这一点,这是我如何看待它。 上面的例子对于初学者来说可能有些过于复杂。
如果你运行这个代码:
var local = true; var global = true; function test(){ var local = false; var global = false; console.log(local) console.log(global) } test(); console.log(local); console.log(global);
输出将读作:false,false,true,true
因为它将函数中的variables视为与其外部的variables分离,因此术语局部variables,这是因为我们在赋值中使用了var。 如果你拿掉了函数中的var,现在它读起来像这样:
var local = true; var global = true; function test(){ local = false; global = false; console.log(local) console.log(global) } test(); console.log(local); console.log(global);
输出是错误的,错误的,错误的,错误的
这是因为不是在本地范围或函数中创build新variables,而是简单地使用全局variables并将其重新赋值为false。
我发现当用var或者不用var来声明variables时,人们会感到困惑。 以下是一个很深的例子,它将引导您完成以下步骤:
请参阅下面的脚本在jsfiddle的行动
a = 1;// Defined outside the function without var var b = 1;// Defined outside the function with var alert("Starting outside of all functions... \n \na, b defined but c, d not defined yet: \na:" + a + "\nb:" + b + "\n \n (If I try to show the value of the undefined c or d, console.log would throw 'Uncaught ReferenceError: c is not defined' error and script would stop running!)"); function testVar1(){ c = 1;// Defined inside the function without var var d = 1;// Defined inside the function with var alert("Now inside the 1. function: \na:" + a + "\nb:" + b + "\nc:" + c + "\nd:" + d); a = a + 5; b = b + 5; c = c + 5; d = d + 5; alert("After added values inside the 1. function: \na:" + a + "\nb:" + b + "\nc:" + c + "\nd:" + d); }; testVar1(); alert("Run the 1. function again..."); testVar1(); function testVar2(){ var d = 1;// Defined inside the function with var alert("Now inside the 2. function: \na:" + a + "\nb:" + b + "\nc:" + c + "\nd:" + d); a = a + 5; b = b + 5; c = c + 5; d = d + 5; alert("After added values inside the 2. function: \na:" + a + "\nb:" + b + "\nc:" + c + "\nd:" + d); }; testVar2(); alert("Now outside of all functions... \n \n Final Values: \na:" + a + "\nb:" + b + "\nc:" + c + "\n You will not be able to see d here because then the value is requested, console.log would throw error 'Uncaught ReferenceError: d is not defined' and script would stop. \n "); alert("**************\n Conclusion \n ************** \n \n 1. No matter declared with or without var (like a, b) if they get their value outside the function, they will preserve their value and also any other values that are added inside various functions through the script are preserved.\n 2. If the variable is declared without var inside a function (like c), it will act like the previous rule, it will preserve its value across all functions from now on. Either it got its first value in function testVar1() it still preserves the value and get additional value in function testVar2() \n 3. If the variable is declared with var inside a function only (like d in testVar1 or testVar2) it will will be undefined whenever the function ends. So it will be temporary variable in a function."); alert("Now check console.log for the error when value d is requested next:"); alert(d);
结论
- 无论是否使用var声明(如a,b),如果它们在函数外获得它们的值,它们将保留它们的值,并且通过脚本保存在各个函数内部添加的任何其他值。
- 如果variables在函数内部没有声明(比如c),就会像之前的规则那样动作,从现在开始它将保留所有函数的值。 要么它获得了函数testVar1()中的第一个值,它仍然保留该值,并在函数testVar2()中获得附加值
- 如果variables只在一个函数中声明为var(比如testVar1或者testVar2中的d),那么只要函数结束,它就不会被定义。 所以它将是一个函数中的临时variables。
除非打算在浏览器中将variables附加到窗口对象,否则应该使用var关键字。 下面是一个链接,解释了glocal作用域和本地作用域之间的区别,以及var关键字和wihtout。
当不使用var关键字定义variables时,看起来像是一个简单的“赋值”操作。
当值被分配给javascript中的variables时,解释器首先尝试在与赋值相同的上下文/作用域中查找“variables声明”。 当解释器执行dummyVariable = 20
,它会在函数开始处查找dummyVariable的声明。 (由于所有的variables声明都被javascript解释器移动到了上下文的开始处,这就叫做提升)
你也可以看看在JavaScript中提升