使用 'var' 声明变量是可选的吗? [复制]

Posted

技术标签:

【中文标题】使用 \'var\' 声明变量是可选的吗? [复制]【英文标题】:Is using 'var' to declare variables optional? [duplicate]使用 'var' 声明变量是可选的吗? [复制] 【发布时间】:2011-01-29 22:27:45 【问题描述】:

“var”是可选的吗?

myObj = 1;

同?

var myObj = 1;

我发现它们在我的测试中都有效,我假设 var 是可选的。对吗?

【问题讨论】:

“可选”可能是一个不幸的单词选择,因为var 是可选的,因为赋值语句可以在有或没有它的情况下成功解释,但在你想要的情况下不是可选的在本地范围内显式声明一个变量。 看看这个小提琴:jsfiddle.net/GWr6Z/2 没有人提到的另一个区别:console.out(var myObj=1) 不起作用,但 console.out(myObj=1) 输出 1。请参阅我的答案(目前在最底部) 【参考方案1】:

它们的含义不同。 如果您使用var,则该变量将在您所在的范围内声明(例如函数)。如果您不使用var,则变量会在范围层中冒泡,直到遇到给定名称或全局对象(窗口,如果您在浏览器中执行此操作)的变量,然后将其附加到该变量。它与全局变量非常相似。但是,它仍然可以使用delete 删除(很可能是其他人的代码也未能使用var)。如果在全局范围内使用var,则变量真正全局,不能删除。

在我看来,这是 javascript 最危险的问题之一,应该弃用,或者至少在警告之上发出警告。原因是,很容易忘记var 并且意外地将一个公共变量名绑定到全局对象。这会产生奇怪且难以调试的行为。

【讨论】:

@精英绅士:是的,它确实使它成为一个全局变量。 @codemeit : javascript 充满了这样的陷阱,但总而言之,它是一种美丽而令人愉快的语言。不要讨厌它。只需了解陷阱并将它们排除在代码之外即可。 自动全局变量从 ECMAScript 5 严格模式中移除,这基本上是一种隐式弃用。如果您在非严格模式下忘记var,希望实现会发出警告。 实际上不,不使用var 分配给变量不会使其全局。它会导致 JS 遍历作用域链,如果变量之前没有在任何地方使用过,最终会到达全局对象。如果变量 在 global 之前的某处使用 var 声明,那么这就是将使用的范围。它也是 JS 工作方式不可或缺的一部分,是什么使它真正强大,所以我不会将其描述为“陷阱”。 @deceze:向上遍历作用域链是件好事,但如果没有找到任何东西,将其添加到全局作用域是一个陷阱。【参考方案2】:

这是 Javascript 的棘手部分之一,但也是其核心功能之一。用var 声明的变量“开始它的生命”就在你声明它的地方。如果你省略了var,就好像你在谈论一个你以前用过的变量。

var foo = 'first time use';
foo = 'second time use';

关于范围, 变量自动成为全局变量是不正确的。相反,Javascript 将遍历作用域链,查看您之前是否使用过该变量。如果它找到一个以前使用过的同名变量的实例,它将使用它以及它声明的任何范围。如果它在任何地方都没有遇到该变量,它最终会命中全局对象(window in浏览器)并将变量附加到它。

var foo = "I'm global";
var bar = "So am I";

function () 
    var foo = "I'm local, the previous 'foo' didn't notice a thing";
    var baz = "I'm local, too";

    function () 
        var foo = "I'm even more local, all three 'foos' have different values";
        baz = "I just changed 'baz' one scope higher, but it's still not global";
        bar = "I just changed the global 'bar' variable";
        xyz = "I just created a new global variable";
    

当与嵌套函数和回调一起使用时,这种行为非常强大。了解 functions 是什么以及作用域如何工作是 Javascript 中最重要的事情。

【讨论】:

这确实是最好的答案,因为了解作用域链的实际行为是理解函数式 Javascript 工作原理的关键——即使您不喜欢以函数式风格编写代码,它也非常好了解有多少常用库确实使用函数式样式。 var foo = 1 不是移到了当前函数作用域的顶部,而不是你声明它的地方吗? foo = 100;bar = 200;(function fooBarDeluxeEdition() bar = 300;//var bar = 400; // try uncommenting this for fun! :)());document.write(bar); @carl 语句本身没有移到顶部,没有。从本质上讲,var 语句将变量名保留在当前范围内,并且它将以 undefined 值开始。初始值的分配只会发生在你写var .. = ..的地方。 @deceze 是的,我有点跑题了。我的意思是,答案(否则很好)表明变量从var 语句开始它的生命。但实际上,如果我没记错的话,所有var 语句都会在函数作用域执行之前被扫描,因此所有变量都在作用域的开头“出生”,即使它们是在var 分配的。这可能是人为的,但我的示例显示了一个场景,您可能会摸不着头脑(尤其是如果您是多页功能的爱好者)。 @carl 好吧,有点公平。它“在范围内开始它的生命”。这样比较合适吗? :)【参考方案3】:

不,它们不相等。

myObj = 1; 使用的是全局变量。

后一个声明会在您使用的范围内创建一个本地变量。

试试下面的代码来理解不同之处:

external = 5;
function firsttry() 
  var external = 6;
  alert("first Try: " + external);


function secondtry() 
  external = 7;
  alert("second Try: " + external);


alert(external); // Prints 5
firsttry(); // Prints 6
alert(external); // Prints 5
secondtry(); // Prints 7
alert(external); // Prints 7

第二个函数改变全局变量“external”的值,但第一个函数没有。

【讨论】:

小心地说“你正在使用一个全局变量”。 “我的对象 = 1;”指的是外部范围内的变量,它可能不是全局的。但是,您的示例确实引用(并可能隐式声明)全局范围内的变量。【参考方案4】:

除了本地与全球之外,还有更多内容。使用var 创建的全局变量与没有创建的全局变量不同。考虑一下:

var foo = 1; // declared properly
bar = 2; // implied global
window.baz = 3; // global via window object

根据目前的答案,这些全局变量foobarbaz 都是等价的。这不是的情况。使用var 生成的全局变量(正确地)分配了内部[[DontDelete]] 属性,因此它们不能被删除。

delete foo; // false
delete bar; // true
delete baz; // true

foo; // 1
bar; // ReferenceError
baz; // ReferenceError

这就是为什么您应该始终使用var,即使对于全局变量也是如此。

【讨论】:

我认为您的见解值得更多曝光,因此我编辑了所选答案以包含此信息。【参考方案5】:

围绕这个主题有很多困惑,现有的答案都没有一个清晰直接地涵盖所有内容。以下是一些内联 cmets 的示例。

//this is a declaration
var foo;

//this is an assignment
bar = 3;

//this is a declaration and an assignment
var dual = 5;

声明设置了 DontDelete 标志。作业没有。

声明将该变量与当前作用域联系起来。

分配但未声明的变量将寻找一个范围来附加自己。这意味着它将遍历作用域的食物链,直到找到具有相同名称的变量。如果没有找到,它将附加到***范围(通常称为全局)。

function example()
  //is a member of the scope defined by the function example
  var foo;

  //this function is also part of the scope of the function example
  var bar = function()
     foo = 12; // traverses scope and assigns example.foo to 12
  


function something_different()
     foo = 15; // traverses scope and assigns global.foo to 15

为了非常清楚地描述正在发生的事情,analysis of the delete function 广泛涵盖了变量实例化和赋值。

【讨论】:

“范围的食物链” => “范围链” 我发现这是对该行为最简洁的解释和演示。我知道这是旧的,但它仍然有效,我认为可以通过调用每个函数来改进它,然后是 foo 的声明,以表明它在第一种情况下会导致错误,并且已神奇地添加到全局范围第二种情况。如果您愿意,我可以自己编辑。【参考方案6】:

var 是可选的。 var 将变量放在本地范围内。如果定义的变量没有var,则它在全局范围内并且不可删除

编辑

我认为不可删除的部分在特定环境的某个时间点是正确的。我一定是做梦了。

【讨论】:

简短,但不正确。如果它是“定义”的,正如你所说的没有 var,你可以删除它。但不使用 var 并不总是声明一个新变量,它可能会在外部范围内引用一个。【参考方案7】:

看看这个小提琴:http://jsfiddle.net/GWr6Z/2/

function doMe()

a = "123"; // will be global
var b = "321"; // local to doMe
alert("a:"+a+"  --  b:"+b);

b = "something else"; // still local (not global)
alert("a:"+a+"  --  b:"+b);

;


doMe()
alert("a:"+a+"  --  b:"+b); // `b` will not be defined, check console.log

【讨论】:

有理智的人对我的 +1 投了低票 简单的解释,感谢 Fiddle【参考方案8】:

They are not the same.

未声明的变量(没有var)被视为全局对象的属性。 (通常是 window 对象,除非你在 with 块中)

var 声明的变量是普通的局部变量,在声明它们的函数之外是不可见的。(请注意,Javascript 没有块作用域)

更新:ECMAScript 2015

let 在 ECMAScript 2015 中被引入以具有块范围

【讨论】:

【参考方案9】:

Javascript 中的 var 关键字是有目的的。

如果你声明一个没有 var 关键字的变量,像这样:

myVar = 100;

它成为一个全局变量,可以从脚本的任何部分访问。如果您不是故意这样做或没有意识到这一点,那么如果您在 javascript 中的其他位置重复使用变量名,可能会导致您痛苦。

如果你用 var 关键字声明变量,像这样:

var myVar = 100;

它在范围内是本地的(] - 大括号、函数、文件,取决于您放置它的位置。

这是一种更安全的变量处理方式。因此,除非您是故意这样做,否则请尝试使用 var 关键字声明变量,而不是没有。

【讨论】:

+1 表示“如果你重复使用变量名,可能会给你带来痛苦” 不是大括号。 JavaScript 变量不是块范围的,而是函数范围的。函数体中任意位置的 var 与函数体顶部的 var 完全相同。【参考方案10】:

考虑一下今天在 *** 上提出的这个问题:

Simple Javascript question

一个好的测试和一个实际的例子是在上述场景中发生的...... 开发人员在他的一个变量中使用了 JavaScript 函数的名称。

代码有什么问题? 该代码仅在用户第一次单击按钮时有效。

解决办法是什么? 在变量名前添加var关键字。

【讨论】:

【参考方案11】:

Var 不允许程序员声明变量,因为 Javascript 没有变量。 Javascript有对象。 Var 显式地为未定义的对象声明一个名称。赋值将名称作为句柄分配给已被赋予值的对象。

使用 var 告诉 Javacript 解释器两件事:

    不使用 delegation 反向遍历查找名称的值,而是使用这个 不要删除名称

var 的省略告诉 Javacript 解释器使用第一个找到的同名对象的先前实例。

Var 作为关键字源于语言设计者的错误决定,就像 Javascript 作为名称源于错误决定一样。

ps。研究上面的代码示例。

【讨论】:

【参考方案12】:

除了范围之外的一切,它们可以以不同的方式使用。

console.out(var myObj=1);
//SyntaxError: Unexpected token var
console.out(myObj=1);
//1

某事某事陈述与表达

【讨论】:

【参考方案13】:

不,它不是“必需的”,但如果您不这样做,它也可能会导致重大问题。不使用 var 定义变量将该变量放在它所在代码部分的范围内。如果不这样做,则它不包含在该范围内,并且可以覆盖以前定义的同名变量,这些变量在范围之外你所在的功能。

【讨论】:

【参考方案14】:

我刚刚从我的一位同事推荐的论坛中找到了答案。如果你在函数之外声明一个变量,它总是全局的。不管你是否使用 var 关键字。但是,如果你在函数中声明变量,它就有很大的不同。在函数内部,如果你使用 var 关键字声明变量,它将是局部的,但如果你声明没有 var 关键字的变量,它将是全局的。它可以覆盖您之前声明的变量。 - 查看更多信息:http://forum.webdeveloperszone.com/question/what-is-the-difference-between-using-var-keyword-or-not-using-var-during-variable-declaration/#sthash.xNnLrwc3.dpuf

【讨论】:

请看前面的答案,你没有添加任何东西。

以上是关于使用 'var' 声明变量是可选的吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

CoreData:Not null 属性应该是可选的吗?

传递给 PDOStatement::bindParam() 的参数名称的前导冒号是可选的吗?

传递给 PDOStatement::bindParam() 的参数名称的前导冒号是可选的吗?

URI 中的 Scheme 是可选的吗?

[react] 自定义组件时render是可选的吗?为什么?

TensorFlow GPU:cudnn 是可选的吗?无法打开 CUDA 库 libcudnn.so