2011-07-31 41 views
33

在W3School有记载:没有var关键字声明变量

如果要声明一个变量,而无需使用“VAR”,变量总是成为全球性的。

在函数内部声明全局变量是否有用?我可以想象在一些事件处理程序中声明了一些全局变量,但是它有什么好处?更好地使用RAM?

回答

69

全局变量是一个坏主意。只有在绝对必要时才能使用它们。没有RAM好处或类似的东西。

w3schools正在谈论的是The Horror of Implicit Globals。考虑一下这个功能:当您运行功能

function foo() { 
    var x; 

    x = 5; 
    y = 6; 
    return x + y; 
} 

,你突然,突然冒出来,有一个名为y全局变量。这是因为该功能分配给y,但y未在任何地方声明。通过JavaScript中的作用域链的机制,这最终将成为全局对象(您可以在浏览器上以window的身份访问)上的属性的隐式赋值。例如,假设y在任何包含范围不申报,这是完全一样的:

function foo() { 
    var x; 

    x = 5; 
    window.y = 6; 
    return x + window.y; 
} 

全局对象包含所有全局(更新:使用来,ES6增加了一个方法来声明全局不会以window结尾,请参阅下面的注释),无论是显式还是隐式定义的。你可以想象有一个很多全球变量是由人们的代码意外创建的。

全局对象已经非常非常混乱。除非你正在编写一个库或一个必须使用多个脚本文件的页面,否则没有理由进一步混淆全局对象。只要定义自己一个很好的范围界定功能,并把你的符号在里面:

(function() { 
    var your, symbols, here, if_they_need, to_be_shared, amongst_functions; 

    function doSomething() { 
    } 

    function doSomethingElse() { 
    } 
})(); 

如果你这样做,你可能想调用JavaScript的新strict mode,添加在第5版规格:

(function() { 
    "use strict"; 
    var your, symbols, here, if_they_need, to_be_shared, amongst_functions; 

    function doSomething() { 
    } 

    function doSomethingElse() { 
    } 
})(); 

...其优点是(amongst other things)使foo函数隐式创建全局变量a ReferenceError


更新:ES6和全局:作为ES6的,一种新的全球性的创建这不是全局对象的属性:全局通过letconst,或class创建。这些新的关键字在全局作用域中使用时,会创建全局对象,这些全局对象不会成为全局对象的属性,因此无法通过浏览器上的window进行访问。

+0

-1因为您的第一句话。全局变量是一个坏主意? **总是?**不,有时他们是一个非常好的主意。这取决于你使用的是什么。讨厌这样的普遍性陈述是不正确的;他们不属于编程。 – Andrew

+1

@Andrew:那么你可以给我第二*句话的功劳。当然,其余的答案弥补了第一句话的问题? –

+0

你的第二句话恭维第一,所以不。全局变量不是一个坏主意,他们往往是一个坏主意。不仅在绝对必要时才使用它们,只要适当地使内存全局可访问就应该使用它们。抱歉,不,“严格使用”不是一种典型的JavaScript理想解决方案,除非您在全球范围内使用它来更像官方的TypeScript;否则这就是你必须不断维护(无处不在)的黑客攻击,以确保你不会编写错误的代码 - 相互矛盾。 – Andrew

3

全局变量的唯一用途是如果您需要全局访问它们。在这种情况下,您应该在函数外部使用var关键字声明它们,以清楚地表明您确实想创建全局变量,并且在尝试声明局部变量时不会忘记var

一般,因此需要尽可能少地在全球范围内,你应该尝试的范围你的代码。您在脚本中使用的全局变量越多,您可以将其与另一个脚本一起使用的机会越少。

正常情况下,函数中的变量应该是本地的,以便它们在您退出函数时消失。

+0

奇怪的是,javascript允许构造不起作用,但只会在我们输入错误时造成麻烦。 – xralf

+1

@xralf:所有语言都允许可能被滥用的构造。 “当(真的);想到的时候。 –

2

有时它有用在其内部可以在以后通过参考窗口对象容易地访问功能创建新的全球可访问的属性(所有全局声明的属性被附着到窗的对象)。

然而,因为它通常是宣布什么是全局访问它会导致一些问题,后来因为这些属性可以很容易地覆盖等,其远不如干脆值传递给函数作为参数并检索其结果。

1

主要问题是别人可能已经在使用全球名称相同的名称。

然后,当您更改全局值时,您将覆盖其值。

后来,当全球下一次使用它会神秘地改变。

+2

“别人”,可能是你,但你忘了你已经在其他地方使用过这个名字了。 – QuentinUK

+0

甚至你的页面上有一个使用'id'的元素,因为所有这些元素都被几乎所有浏览器的'window'对象占用。 (我认为Firefox是唯一的坚持。) –

16

副作用当忘记VAR

有隐含的全局和明确定义的人之间的一个细微的差别。 区别在于使用删除操作符取消定义这些变量的能力:

•无法删除使用var创建的全局变量(在程序外部创建的变量) 。

•(如果在函数内部创建不分),而VAR创建隐含的全局可 删除。

这表明,隐含的全局在技术上是不是真正的变量,但它们的属性的全局对象的 。属性可以与删除操作员,而变量被删除 不能:

// define three globals 
var global_var = 1; 
global_novar = 2; // antipattern 
(function() { 
    global_fromfunc = 3; // antipattern 
}()); 
// attempt to delete 
delete global_var; // false 
delete global_novar; // true 
delete global_fromfunc; // true 
// test the deletion 
typeof global_var; // "number" 
typeof global_novar; // "undefined" 
typeof global_fromfunc; // "undefined" 

在ES5严格模式,分配给未声明的变量(如在前面的代码段在两个反模式 )将抛出异常。

JavaScript的模式,由斯托扬斯特凡(O'Reilly出版)。 Copyright 2010 Yahoo !, Inc.,9780596806750.

+0

//在变量结果类型中需要稍作修改当我试图在w3school编译器中运行上面的变量声明时,我得到了alert(typeof global_var); //数字警报(typeof global_novar); // number alert(typeof global_fromfunc); // undefined –

+0

有用的解释!谢谢 :) –