使用 '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
根据目前的答案,这些全局变量foo
、bar
和baz
都是等价的。这不是的情况。使用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' 声明变量是可选的吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
传递给 PDOStatement::bindParam() 的参数名称的前导冒号是可选的吗?
传递给 PDOStatement::bindParam() 的参数名称的前导冒号是可选的吗?