var 关键字的用途是什么以及何时应该使用它(或省略它)?
注意:这个问题是从 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;
之间有什么区别?
你什么时候会使用其中任何一个,为什么/它有什么作用?
NOTE: This question was asked from the viewpoint of ECMAScript version 3 or 5. The answers might become outdated with the introduction of new features in the release of ECMAScript 6.
What exactly is the function of the var
keyword in JavaScript, and what is the difference between
var someNumber = 2;
var someFunction = function() { doSomething; }
var someObject = { }
var someObject.someProperty = 5;
and
someNumber = 2;
someFunction = function() { doSomething; }
someObject = { }
someObject.someProperty = 5;
?
When would you use either one, and why/what does it do?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(19)
如果你在全球范围内,那么没有太大区别。阅读 Kangax 的 答案以获取解释
如果您在函数中,则
var
将创建一个局部变量,“no var”将查找作用域链,直到找到该变量或到达全局作用域(此时它将创建它):如果您没有进行赋值,那么您需要使用
var
:If you're in the global scope then there's not much difference. Read Kangax's answer for explanation
If you're in a function then
var
will create a local variable, "no var" will look up the scope chain until it finds the variable or hits the global scope (at which point it will create it):If you're not doing an assignment then you need to use
var
:有区别。
var x = 1
在当前作用域(也称为执行上下文)中声明变量x
。如果声明出现在函数中 - 声明了局部变量;如果它在全局范围内 - 声明一个全局变量。另一方面,
x = 1
只是一个属性赋值。它首先尝试根据作用域链解析x
。如果它在该作用域链中的任何位置找到它,它就会执行分配;如果它没有找到x
,那么它才会在全局对象上创建x
属性(这是范围内的顶级对象)链)。现在,请注意,它没有声明全局变量,而是创建了一个全局属性。
两者之间的区别很微妙,可能会令人困惑,除非您了解变量声明也会创建属性(仅在变量对象上)并且 Javascript(好吧,ECMAScript)中的每个属性都有某些描述的标志它们的属性 - ReadOnly、DontEnum 和 DontDelete。
由于变量声明使用 DontDelete 标志创建属性,因此
var x = 1
和x = 1
(在全局范围内执行时)之间的区别在于,前者 - 变量声明- 创建 DontDelete'able 属性,而后一个则没有。因此,通过此隐式赋值创建的属性可以从全局对象中删除,而前一个属性(通过变量声明创建的属性)则无法删除。但这当然只是理论,在实践中,由于实现中的各种错误(例如来自 IE 的错误),两者之间存在更多差异。
希望这一切都有意义 :)
[更新 2010/12/16]
在 ES5(ECMAScript 5;最近标准化的语言第 5 版)中,有一种所谓的“严格模式”——一种可选模式在语言模式下,这会稍微改变未声明赋值的行为。在严格模式下,分配给未声明的标识符会引发ReferenceError。这样做的理由是捕获意外分配,防止创建不需要的全局属性。一些较新的浏览器已经开始滚动支持严格模式。例如,请参阅我的兼容性表。
There's a difference.
var x = 1
declares variablex
in current scope (aka execution context). If the declaration appears in a function - a local variable is declared; if it's in global scope - a global variable is declared.x = 1
, on the other hand, is merely a property assignment. It first tries to resolvex
against scope chain. If it finds it anywhere in that scope chain, it performs assignment; if it doesn't findx
, only then does it createsx
property on a global object (which is a top level object in a scope chain).Now, notice that it doesn't declare a global variable, it creates a global property.
The difference between the two is subtle and might be confusing unless you understand that variable declarations also create properties (only on a Variable Object) and that every property in Javascript (well, ECMAScript) have certain flags that describe their properties - ReadOnly, DontEnum and DontDelete.
Since variable declaration creates property with the DontDelete flag, the difference between
var x = 1
andx = 1
(when executed in global scope) is that the former one - variable declaration - creates the DontDelete'able property, and latter one doesn't. As a consequence, the property created via this implicit assignment can then be deleted from the global object, and the former one - the one created via variable declaration - cannot be deleted.But this is just theory of course, and in practice there are even more differences between the two, due to various bugs in implementations (such as those from IE).
Hope it all makes sense : )
[Update 2010/12/16]
In ES5 (ECMAScript 5; recently standardized, 5th edition of the language) there's a so-called "strict mode" — an opt-in language mode, which slightly changes the behavior of undeclared assignments. In strict mode, assignment to an undeclared identifier is a ReferenceError. The rationale for this was to catch accidental assignments, preventing creation of undesired global properties. Some of the newer browsers have already started rolling support for strict mode. See, for example, my compat table.
说这是“本地”和“全球”之间的区别并不完全准确。
最好将其视为“本地”和“最近”之间的差异。最近的肯定可以是全球性的,但情况并非总是如此。
Saying it's the difference between "local and global" isn't entirely accurate.
It might be better to think of it as the difference between "local and nearest". The nearest can surely be global, but that won't always be the case.
当 Javascript 在浏览器中执行时,所有代码都被 with 语句包围,如下所示:
有关
with
- MDN由于
var
声明了一个变量 在当前作用域 ,因此声明 < code>var 在窗口内并且根本不声明它。当您不直接在窗口内(例如在函数内或块内)时,就会出现差异。
使用
var
可以隐藏同名的外部变量。通过这种方式,你可以模拟一个“私有”变量,但那是另一个话题了。经验法则是始终使用
var
,否则您将面临引入细微错误的风险。编辑:
在收到批评后,我想强调以下几点:
var
声明了一个变量 在当前作用域window
var
在全局作用域(窗口)中隐式声明var
var
在全局作用域(窗口)中声明变量与省略它相同。var
在不同于 window 的作用域中声明变量 与不使用var
声明变量不同var 明确地因为这是一个很好的实践
When Javascript is executed in a browser, all your code is surrounded by a with statement, like so:
More info on
with
- MDNSince
var
declares a variable in the current scope , there is no difference between declaringvar
inside window and not declaring it at all.The difference comes when you're not directly inside the window, e.g. inside a function or inside a block.
Using
var
lets you hide external variables that have the same name. In this way you can simulate a "private" variable, but that's another topic.A rule of thumb is to always use
var
, because otherwise you run the risk of introducing subtle bugs.EDIT:
After the critiques I received, I would like to emphasize the following:
var
declares a variable in the current scopewindow
var
implicitly declaresvar
in the global scope (window)var
is the same as omitting it.var
is not the same thing as declaring a variable withoutvar
var
explicitly because it's good practice始终使用
var
关键字来声明变量。为什么?良好的编码实践本身就应该有足够的理由,但省略它意味着它是在全局范围内声明的(这样的变量称为“隐含”全局)。 Douglas Crockford 建议永远不要使用隐含全局变量,并根据 Apple JavaScript 编码指南:Always use the
var
keyword to declare variables. Why? Good coding practice should be enough of a reason in itself, but omitting it means it is declared in the global scope (a variable like this is called an "implied" global). Douglas Crockford recommends never using implied globals, and according to the Apple JavaScript Coding Guidelines:这是一个很好的例子,说明了如何因未使用
var
声明局部变量而陷入困境:(
i
在循环的每次迭代中都会重置,因为它是不是在for
循环中局部声明,而是全局声明)最终导致无限循环Here's quite a good example of how you can get caught out from not declaring local variables with
var
:(
i
is reset at every iteration of the loop, as it's not declared locally in thefor
loop but globally) eventually resulting in infinite loop我想说在大多数情况下最好使用
var
。局部变量总是比全局范围内的变量更快。
如果不使用
var
声明变量,则该变量将处于全局范围内。有关更多信息,您可以在 Google 中搜索“作用域链 JavaScript”。
I would say it's better to use
var
in most situations.Local variables are always faster than the variables in global scope.
If you do not use
var
to declare a variable, the variable will be in global scope.For more information, you can search "scope chain JavaScript" in Google.
不要使用
var
!var
是 ES6 之前声明变量的方式。我们现在在未来,你应该这样编码。使用
const
和let
const
应该在大约 95% 的情况下使用。它使得变量引用无法更改,因此数组、对象和 DOM 节点属性可以更改,并且应该是 const。let
应该用于任何需要重新分配的变量。这包括在 for 循环内。如果您在初始化之外编写了varName =
,请使用let
。正如大多数其他语言所期望的那样,两者都具有块级作用域。
Don't use
var
!var
was the pre-ES6 way to declare a variable. We are now in the future, and you should be coding as such.Use
const
andlet
const
should be used for ~95% of cases. It makes it so the variable reference can't change, thus array, object, and DOM node properties can change and should likely beconst
.let
should be be used for any variable expecting to be reassigned. This includes within a for loop. If you ever writevarName =
beyond the initialization, uselet
.Both have block level scoping, as expected in most other languages.
另一个区别
例如,
同时
another difference
e.g
while
使用
var
始终是一个好主意,可以防止变量使全局范围混乱以及变量之间相互冲突,从而导致不必要的覆盖。Using
var
is always a good idea to prevent variables from cluttering the global scope and variables from conflicting with each other, causing unwanted overwriting.没有
var
- 全局变量。强烈建议始终使用
var
语句,因为本地上下文中的init全局变量是邪恶的。但是,如果你需要这个肮脏的把戏,你应该在页面开头写下评论:Without
var
- global variable.Strongly recommended to ALWAYS use
var
statement, because init global variable in local context - is evil. But, if you need this dirty trick, you should write comment at start of page:这是我为您编写的示例代码,以帮助您理解这个概念:
This is example code I have written for you to understand this concept:
@Chris S 给出了一个很好的例子,展示了
var
和没有var
之间的实际差异(和危险)。这是另一个,我发现这个特别危险,因为差异仅在异步环境中可见,因此在测试过程中很容易被忽略。正如您所期望的,以下代码片段输出
["text"]
:以下代码片段也是如此(请注意
array
之前缺少let
):使用单个执行器异步执行数据操作仍然会产生相同的结果:
但对于多个的行为有所不同:
然而使用let:
@Chris S gave a nice example showcasing the practical difference (and danger) between
var
and novar
. Here's another one, I find this one particularly dangerous because the difference is only visible in an asynchronous environment so it can easily slip by during testing.As you'd expect the following snippet outputs
["text"]
:So does the following snippet (note the missing
let
beforearray
):Executing the data manipulation asynchronously still produces the same result with a single executor:
But behaves differently with multiple ones:
Using let however:
作为一个试图学习这一点的人,我就是这样看待它的。上面的例子对于初学者来说可能有点过于复杂。
如果运行此代码:
输出将读为: false, false, true, true
因为它将函数中的变量与函数外部的变量分开,因此出现术语“局部变量”,这是因为我们在赋值中使用了 var 。如果你去掉函数中的 var,那么它现在的读法如下:
输出是 false, false, false, false
这是因为它不是在局部作用域或函数中创建新变量,而是简单地使用全局变量并重新分配它们为假。
As someeone trying to learn this this is how I see it. The above examples were maybe a bit overly complicated for a beginner.
If you run this code:
The output will read as: false, false, true, true
Because it sees the variables in the function as seperate from those outside of it, hence the term local variable and this was because we used var in the assignment. If you take away the var in the function so it now reads like this:
The output is false, false, false, false
This is because rather than creating a new variable in the local scope or function it simply uses the global variables and reassigns them to false.
我发现人们在使用或不使用 var 以及函数内部或外部声明变量时感到困惑。下面是一个深入的示例,将引导您完成这些步骤:
在 jsfiddle 上查看下面的脚本
I see people are confused when declaring variables with or without var and inside or outside the function. Here is a deep example that will walk you through these steps:
See the script below in action here at jsfiddle
在代码中,如果您使用变量而不使用 var,那么会发生的情况是 var var_name 自动放置在全局范围中,例如:
Inside a code you if you use a variable without using var, then what happens is the automatically var var_name is placed in the global scope eg:
除了范围问题之外,有些人还提到了 提升,但没有人给出示例。这是全球范围的:
Besides scopes issue, some folks also mention hoisting, but no one gave an example. Here's one for global scope:
不使用“var”变量只能在设置值时定义。例如:
无法在全局范围或任何其他范围中工作。它应该具有如下值:
另一方面,您可以定义一个可用的值;
它的值是
undefined
(它的值不是null
,而且有趣的是它不等于null
)。Without using "var" variables can only define when set a value. In example:
cannot work in global scope or any other scope. It should be with value like:
On the other hand you can define a vaiable like;
Its value is
undefined
( Its value is notnull
and it is not equal tonull
interestingly.).您应该使用 var 关键字,除非您打算将变量附加到浏览器中的 window 对象。 这是一个解释范围界定和glocal 作用域和使用或不使用 var 关键字的局部作用域之间的区别。
当不使用 var 关键字定义变量时,它看起来像是一个简单的“赋值”操作。
当在 javascript 中将值赋给变量时,解释器首先尝试在与赋值相同的上下文/范围中查找“变量声明”。当解释器执行 dummyVariable = 20 时,它会在函数开头查找 dummyVariable 的声明。
(因为所有变量声明都被 javascript 解释器移动到上下文的开头,这称为提升)
您可能还需要查看 在 javascript 中提升
You should use var keyword unless you intend to have the variable attached to window object in browser. Here's a link that explains scoping and difference between glocal scoping and local scoping with and wihtout var keyword.
When variables get defined without the use of var keyword, what it looks like is a simple “assignment” operation.
When the value is assigned to a variable in javascript, the interpreter first tries to find the “variable declaration” in the same context/scope as that of assignment. When the interpreter executes
dummyVariable = 20
, it looks up for the declaration of dummyVariable at beginning of the function.(Since all Variable declarations are moved to the beginning of the context by javascript interpreter and this is called hoisting)
You may also want to look at hoisting in javascript