1631

注意:这个问题是从 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;

?

你什么时候会使用其中任何一个,为什么/它做什么?

4

19 回答 19

1403

如果您在全球范围内,那么差别不大。阅读Kangax 的答案以获得解释

如果你在一个函数中,那么var将创建一个局部变量,“no var”将查找作用域链,直到它找到变量或到达全局作用域(此时它将创建它):

// 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
于 2009-09-24T08:55:47.283 回答
770

有区别

var x = 1 在当前范围内声明变量 x(又名执行上下文)。如果声明出现在函数中 - 声明了一个局部变量;如果它在全局范围内 - 声明一个全局变量。

x = 1另一方面,它仅仅是一个属性分配。它首先尝试解决x作用域链。如果它在该范围链中的任何位置找到它,它就会执行分配;如果它没有找到x,那么它只会在全局对象(它是作用域链中的顶级对象)上创建属性。x

现在,请注意它没有声明一个全局变量,它创建了一个全局属性。

两者之间的区别是微妙的并且可能会令人困惑,除非您了解变量声明也会创建属性(仅在变量对象上)并且 Javascript(嗯,ECMAScript)中的每个属性都有某些描述其属性的标志 - ReadOnly、DontEnum 和不要删除。

var x = 1由于变量声明创建带有 DontDelete 标志的属性,和(在全局范围内执行时)之间的区别在于x = 1前者 - 变量声明 - 创建了 DontDelete'able 属性,而后者没有。因此,通过这个隐式赋值创建的属性可以从全局对象中删除,而前一个 - 通过变量声明创建的属性 - 不能被删除。

但这当然只是理论,实际上两者之间存在更多差异,这是由于实现中的各种错误(例如来自 IE 的错误)。

希望这一切都有意义:)


[2010/12/16 更新]

在 ES5(ECMAScript 5;最近标准化,该语言的第 5 版)中有一种所谓的“严格模式”——一种选择性加入的语言模式,它略微改变了未声明赋值的行为。在严格模式下,分配给未声明的标识符是ReferenceError。这样做的基本原理是捕获意外分配,防止创建不需要的全局属性。一些较新的浏览器已经开始滚动支持严格模式。例如,请参阅我的兼容表

于 2009-09-24T13:38:36.340 回答
142

说这是“本地全球”之间的区别并不完全准确。

将其视为“本地最近”之间的区别可能会更好。最近的肯定可以是全球性的,但情况并非总是如此。

/* 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;
    }
}
于 2009-09-24T09:50:34.373 回答
85

在浏览器中执行 Javascript 时,所有代码都被 with 语句包围,如下所示:

with (window) {
    //Your code
}

更多信息with- MDN

由于在当前范围内var声明了一个变量,因此在 window 内部声明和根本不声明它没有区别。var

当您不在窗口内时,例如在函数内或块内时,差异就出现了。

使用var允许您隐藏具有相同名称的外部变量。通过这种方式,您可以模拟“私有”变量,但这是另一个主题。

经验法则是始终使用var,否则您将面临引入细微错误的风险。

编辑:在收到批评后,我想强调以下几点:

  • var在当前范围内声明一个变量
  • 全局范围是window
  • 不在全局范围内使用var隐式声明var(窗口)
  • 在全局范围(窗口)中声明一个变量 usingvar与省略它相同。
  • 在与 window using 不同的范围内声明变量与在var 没有的情况下声明变量不同var
  • 始终var明确声明,因为这是一种很好的做法
于 2009-09-24T09:17:57.347 回答
50

始终使用var关键字来声明变量。为什么?良好的编码实践本身就足够了,但省略它意味着它是在全局范围内声明的(这样的变量称为“隐含”全局)。Douglas Crockford建议不要使用隐含的全局变量,并且根据Apple JavaScript 编码指南

没有关键字创建的任何变量var 都是在全局范围内创建的,并且在函数返回时不会被垃圾收集(因为它不会超出范围),这会带来内存泄漏的机会。

于 2009-09-24T09:52:16.533 回答
33

这是一个很好的例子,说明如何不使用声明局部变量而陷入困境var

<script>
one();

function one()
{
    for (i = 0;i < 10;i++)
    {
        two();
        alert(i);
    }
}

function two()
{
    i = 1;
}
</script>

i在循环的每次迭代中重置,因为它不是在for循环中本地声明而是全局声明)最终导致无限循环

于 2009-09-24T09:31:30.197 回答
17

var我会说在大多数情况下使用它会更好。

局部变量总是比全局范围内的变量快。

如果不使用var声明变量,则该变量将在全局范围内。

更多信息,您可以在 Google 中搜索“范围链 JavaScript”。

于 2009-09-24T09:02:54.507 回答
14

不要使用var

var是 ES6 之前声明变量的方式。我们现在在未来,你应该这样编码。

使用constlet

const应该用于约 95% 的情况。它使得变量引用不能改变,因此数组、对象和 DOM 节点属性可以改变并且应该是const.

let应该用于期望被重新分配的任何变量。这包括在 for 循环中。如果您varName =在初始化之外编写过代码,请使用let.

正如大多数其他语言所预期的那样,两者都具有块级范围。

于 2017-08-15T18:49:45.743 回答
12

另一个区别,例如

var a = a || [] ; // works 

尽管

a = a || [] ; // a is undefined error.
于 2013-08-09T22:11:28.957 回答
11

没有var- 全局变量。

强烈建议始终使用var语句,因为在本地上下文中初始化全局变量 - 是邪恶的。但是,如果你需要这个肮脏的技巧,你应该在页面开头写评论:

/* global: varname1, varname2... */
于 2009-09-24T09:04:48.503 回答
11

使用var始终是防止变量混淆全局范围和变量相互冲突的好主意,从而导致不必要的覆盖。

于 2011-04-04T23:14:43.373 回答
6

这是我为您编写的示例代码,用于理解这个概念:

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
于 2013-10-27T14:27:40.270 回答
6

var@Chris S 给出了一个很好的例子,展示了和 no之间的实际差异(和危险)var。这是另一个,我发现这个特别危险,因为差异仅在异步环境中可见,因此在测试过程中很容易溜走。

如您所料,以下代码段输出["text"]

function var_fun() {
  let array = []
  array.push('text')
  return array
}

console.log(var_fun())

以下代码段也是如此(注意let之前的缺失array):

function var_fun() {
  array = []
  array.push('text')
  return array
}

console.log(var_fun())

异步执行数据操作仍然会使用单个执行器产生相同的结果:

function var_fun() {
  array = [];
  return new Promise(resolve => resolve()).then(() => {
    array.push('text')
    return array
  })
}

var_fun().then(result => {console.log(result)})

但与多个不同的行为不同:

function var_fun() {
  array = [];
  return new Promise(resolve => resolve()).then(() => {
    array.push('text')
    return array
  })
}

[1,2,3].forEach(i => {
  var_fun().then(result => {console.log(result)})
})

但是使用 let :

function var_fun() {
  let array = [];
  return new Promise(resolve => resolve()).then(() => {
    array.push('text')
    return array
  })
}

[1,2,3].forEach(i => {
  var_fun().then(result => {console.log(result)})
})

于 2017-12-29T00:46:27.233 回答
5

作为试图学习这一点的人,这就是我的看法。对于初学者来说,上面的例子可能有点过于复杂。

如果您运行此代码:

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);

输出将读取为:假,假,真,真

因为它认为函数中的变量与函数外部的变量是分开的,所以术语局部变量是因为我们在赋值中使用了 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);

输出为假,假,假,假

这是因为它不是在本地范围或函数中创建新变量,而是简单地使用全局变量并将它们重新分配为 false。

于 2016-10-01T03:14:08.483 回答
5

我看到人们在声明带有或不带有var以及在函数内部或外部的变量时感到困惑。这是一个深入的示例,将引导您完成这些步骤:

在 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 \n a, b defined but c, d not defined yet: \n a:" + a + "\n b:" + 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: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);

    a = a + 5;
    b = b + 5;
    c = c + 5;
    d = d + 5;

    alert("After added values inside the 1. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + 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: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);

    a = a + 5;
    b = b + 5;
    c = c + 5;
    d = d + 5;

    alert("After added values inside the 2. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);
};

testVar2();

alert("Now outside of all functions... \n \n Final Values: \n a:" + a + "\n b:" + b + "\n c:" + 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);

结论

  1. 无论是否声明了 var(如 a、b),如果它们在函数外部获取值,它们将保留它们的值,并且通过脚本添加到各种函数内的任何其他值也将被保留。
  2. 如果在函数(如 c)中声明变量时没有 var,它将像之前的规则一样,从现在开始在所有函数中保留其值。它要么在函数 testVar1() 中获得第一个值,它仍然保留该值并在函数 testVar2() 中获得附加值
  3. 如果变量仅在函数内部用 var 声明(如 testVar1 或 testVar2 中的 d),那么每当函数结束时,它将是未定义的。所以它将是函数中的临时变量。
于 2016-11-20T06:50:32.733 回答
4

在代码中,如果您在不使用 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 i.e. gives b global scope or
    uses already defined global variable b */
}
于 2013-08-13T23:00:22.227 回答
4

除了范围问题,有些人还提到了提升,但没有人举个例子。这是全球范围的一个:

console.log(noErrorCase);
var noErrorCase = "you will reach that point";

console.log(runTimeError);
runTimeError = "you won't reach that point";

于 2019-09-05T10:24:07.097 回答
3

不使用“var”的变量只能在设置值时定义。例如:

my_var;

不能在全局范围任何其他范围内工作。它应该具有如下值:

my_var = "value";

另一方面,您可以定义一个 vaiable like;

var my_var;

它的值是undefined(它的值不是,有趣null的是它不等于null。)。

于 2014-04-27T04:28:08.593 回答
3

除非您打算将变量附加到浏览器中的窗口对象,否则您应该使用 var 关键字。这是一个链接,它解释了 glocal 作用域和使用 var 关键字的本地作用域之间的作用域和区别。

当变量在不使用 var 关键字的情况下定义时,它看起来像是一个简单的“赋值”操作。

当值被分配给 javascript 中的变量时,解释器首先尝试在与分配相同的上下文/范围中找到“变量声明”。当解释器执行dummyVariable = 20时,它会在函数的开头查找 dummyVariable 的声明。(由于所有变量声明都被 javascript 解释器移动到上下文的开头,这称为提升)

您可能还想查看javascript 中的提升

于 2016-12-12T04:22:34.800 回答