注意:从ECMAScript版本3或5的角度提出了这个问题 . 在ECMAScript 6发布中引入新功能后,答案可能会过时 .
JavaScript中 var
关键字的功能到底是什么,有什么区别
var someNumber = 2;
var someFunction = function() { doSomething; }
var someObject = { }
var someObject.someProperty = 5;
和
someNumber = 2;
someFunction = function() { doSomething; }
someObject = { }
someObject.someProperty = 5;
?
你什么时候使用其中任何一个,为什么/它做什么?
18 回答
使用
var
始终是一个好主意,以防止变量混乱全局范围和变量相互冲突,从而导致不必要的覆盖 .如果你're in the global scope then there'没什么区别 . 阅读Kangax's答案进行解释
如果你在函数中,那么 var 将创建一个局部变量,"no var"将查找范围链,直到它找到变量或命中全局范围(此时它将创建它):
如果你没有做任务,那么你需要使用
var
:There's a difference .
var x = 1
declares variablex
在当前范围内(也称为执行上下文) . 如果声明出现在函数中 - 声明了局部变量;如果它在全局范围内 - 声明了一个全局变量 .另一方面,
x = 1
仅仅是 property 分配 . 它首先尝试针对作用域链解析x
. 如果它在该范围链中的任何位置找到它,它将执行赋值;如果找不到x
,则只有 it creates x property on a global object (这是作用域链中的顶级对象) .现在,请注意它没有声明全局变量,它会创建一个全局属性 .
两者之间的区别是微妙的,可能会让人感到困惑,除非你理解 variable declarations also create properties (仅在变量对象上)并且Javascript中的每个属性(好吧,ECMAScript)都有某些描述其属性的标志 - ReadOnly,DontEnum和DontDelete .
由于变量声明使用DontDelete标志创建属性,因此
var x = 1
和x = 1
(在全局范围内执行时)之间的区别在于前一个 - 变量声明 - 创建DontDelete 'able property, and latter one doesn' t . 因此,可以从全局对象中删除通过此隐式赋值创建的属性,并且不能删除前一个 - 通过变量声明创建的属性 .但这当然只是理论,并且由于实现中的各种错误(例如来自IE的错误) .
希望这一切都有道理:)
[Update 2010/12/16]
在ES5(ECMAScript 5;最近标准化,该语言的第5版)中,有一种所谓的"strict mode" - 一种选择加入语言模式,它略微改变了未声明的作业的行为 . 在严格模式下,对未声明标识符的分配是 ReferenceError . 这样做的理由是捕获意外分配,防止产生不希望的全局属性 . 一些较新的浏览器已经开始支持严格模式 . 例如,见my compat table .
说它是“ local 和 global ”之间的区别并不完全准确 .
将它视为“ local 和 nearest ”之间的区别可能会更好 . 最近的肯定是全球性的,但情况并非总是如此 .
当Javascript在浏览器中执行时,所有代码都被with语句包围,如下所示:
更多信息with - MDN
由于
var
在当前范围内声明了一个变量,因此声明var
inside window 并且根本不声明它之间没有区别 .当你没有直接进入窗户时,就会产生差异,例如:在函数内部或块内部 .
使用
var
可以隐藏具有相同名称的外部变量 . 通过这种方式,您可以模拟"private"变量,但这是另一个主题 .一个经验法则是始终使用
var
,否则您将面临引入细微错误的风险 .编辑:在收到批评后,我想强调以下内容:
var
在当前范围内声明变量全球范围是
window
不使用
var
在全局范围(窗口)中隐式声明var
使用
var
在全局范围(窗口)中声明变量与省略它相同 .使用
var
is not the same thing 声明与窗口不同的作用域中的变量,因为声明不带var
的变量始终明确声明
var
,因为这是一种很好的做法您应该始终使用
var
关键字来声明变量 . 为什么?良好的编码实践本身就足够了,但是声明一个没有var
关键字的变量意味着它在 global 范围内声明(像这样的变量称为"implied" global) . Douglas Crockford recommends never using implied globals,并根据Apple JavaScript Coding Guidelines:因此,简而言之,始终使用
var
关键字声明变量 .这里的一个很好的例子,说明如何通过
var
来声明局部变量:(
i
在循环的每次迭代时都会重置,因为它没有在for
循环中本地声明但是全局声明)最终导致无限循环我想说在大多数情况下使用 var 会更好 .
局部变量总是比全局范围内的变量快 .
如果不使用 var 声明变量,则变量将位于全局范围内 .
有关详细信息,您可以在Google中搜索“范围链JavaScript” .
另一个不同之处
而
没有
var
- 全局变量 .强烈建议 ALWAYS 使用
var
语句,因为在本地上下文中的init全局变量 - 是邪恶的 . 但是,如果你需要这个肮脏的技巧,你应该在页面开头写评论:不要使用var!
var
是ES6之前声明变量的方式 . 我们现在在将来,你应该这样编码 .使用const和let
const
应该用于95%的案例 . 它使得变量引用无法更改,因此数组,对象和DOM节点属性可以更改,并且可能应该是const
.let
应该用于任何期望被重新分配的变量 . 这包括在for循环中 . 如果您在初始化之后编写varName =
,请使用let
.两者都具有块级别范围,正如大多数其他语言所预期的那样 .
这是我为您编写的示例代码,用于理解此概念:
在代码中,如果您在不使用var的情况下使用变量,那么会发生的情况是自动var var_name被放置在全局范围中,例如:
不使用“var”变量只能定义何时设置值 . 例如:
无法在 global scope 或 any other scope 中工作 . 它应该具有如下 Value :
另一方面,你可以定义一个像vaiable;
它的值是
undefined
(它的值不是null
并且它有趣地不等于null
. ) .正如有人试图了解这一点,这就是我的看法 . 对于初学者来说,上面的例子可能有点过于复杂 .
如果您运行此代码:
输出将显示为:false,false,true,true
因为它将函数中的变量视为与其外部的变量分开,因此术语局部变量,这是因为我们在赋值中使用了var . 如果你拿走函数中的var,那么它现在看起来像这样:
输出为false,false,false,false
这是因为它不是在局部范围或函数中创建新变量,而是简单地使用全局变量并将它们重新指定为false .
在使用或不使用 var 以及函数内部或外部声明变量时,我看到人们感到困惑 . 这是一个深入的示例,将引导您完成以下步骤:
See the script below in action here at jsfiddle
您应该使用var关键字,除非您打算在浏览器中将变量附加到window对象 . Here's a link that explains scoping and difference between glocal scoping and local scoping with and wihtout var keyword.
当变量在不使用var关键字的情况下定义时,它看起来像是一个简单的“赋值”操作 .
当在javascript中将值赋给变量时,解释器首先尝试在与赋值相同的上下文/范围中查找“变量声明” . 当解释器执行
dummyVariable = 20
时,它会在函数开头查找dummyVariable的声明 . (因为所有变量声明都通过javascript解释器移动到上下文的开头,这称为提升)你可能还想看hoisting in javascript
@Chris S给出了一个很好的例子,展示了
var
和没有var
之间的实际差异(和危险) . 这是另一个,我发现这个特别危险,因为差异仅在异步环境中可见,所以它在测试期间很容易漏掉 .正如您所期望的那样,以下代码段输出
["text"]
:以下代码段也是如此(注意在
array
之前缺少let
):异步执行数据操作仍然会产生与单个执行程序相同的结果:
但对多个行为有不同的表现:
然而,使用let: