【问题标题】:Why are global variables considered bad practice?为什么全局变量被认为是不好的做法?
【发布时间】:2012-05-18 12:41:16
【问题描述】:

我不断看到不要在 JavaScript 中使用全局变量的警告,但似乎人们这么说的唯一原因是因为阻塞了全局命名空间。我可以想象通过将所有变量放入一个大对象中很容易解决这个问题。现在的问题是:除了方便起见,还有其他理由不使用全局变量吗?它们是否存在任何性能或兼容性问题?

【问题讨论】:

标签: javascript global-variables global


【解决方案1】:

它们使全局命名空间变得混乱,查找起来比局部变量慢。

首先,拥有许多全局变量总是一件坏事,因为很容易忘记您在某处声明了一个变量并意外地在其他地方重新声明了它。如果您的第一个变量是本地变量,那么您没有问题。如果它是全局的,那么它就会被覆盖。当您进入隐含的全局变量时(例如,当您说 someVar = someValue 而不使用 var 关键字声明 someVar 时)情况会变得更糟。

其次,全局变量在 Javascript 中“查找”的时间比局部变量要长。速度上的差异并不大,但它确实存在。

要进一步阅读和更深入地解释为什么全局变量被认为是不好的做法,您可能需要查看this page

【讨论】:

  • 如果你重新声明它,你会得到一个编译器错误。但我知道你的意思,你的意思是如果你在错误的地方重新使用它,你的代码会很轻微地失败,你会对出了什么问题感到困惑。
【解决方案2】:

全局变量会显着增加耦合,显着降低代码的可扩展性和可测试性。一旦你开始使用全局变量,你现在必须知道变量在哪里以及如何被修改(即打破封装)。大多数文献和惯例都认为,在使用全局变量时,性能是您最不关心的问题。

这是一个fantastic article outlining why全局变量引起的头痛。

【讨论】:

    【解决方案3】:

    简而言之,全局变量会导致(以及更多)以下问题。

    1) 变量命名冲突 - 如果您在一个团队中工作并且您自己和您的同事在全局范围内使用相同的变量名称,最后定义的变量将覆盖初始变量。这种明显的后果可能会产生毁灭性的后果。

    2) 安全性 - 特别是在网络上,每个用户都可以访问 Window(或全局)对象。通过将变量放在全局范围内,您可以让任何用户查看或更改您的变量。

    3) 较慢 - 这可以说可以忽略不计,但它仍然存在。 JavaScript 变量查找的工作方式是 JavaScript 引擎将对正在查找的变量的当前作用域进行查找。如果找不到它,它将在下一个父作用域上进行查找。如果它在那里没有找到它,它将继续向上查找,直到它到达寻找该变量的全局对象。如果您的所有变量都位于全局范围内,JavaScript 引擎将始终必须遍历每个范围才能最终到达全局范围以找到变量。

    【讨论】:

      【解决方案4】:

      如果你的脚本很长并且你从很多函数中使用这些变量,它会增加你的调试时间,因为全局变量的值可能已经从任何地方改变了,所以如果你正在跟踪这个改变到非预期的地方值,您必须全部检查。

      如果不同的程序员从您页面中包含的其他脚本修改此变量,这种情况会更加痛苦。

      【讨论】:

      【解决方案5】:

      在代码中使用全局变量应该没有任何问题,只要您将它们包装在唯一的命名空间/对象中(以避免与不属于您的脚本发生冲突)

      在 javascript 中使用全局变量有一个好处,它源于 javascript 不是一种强类型语言这一事实​​。因此,如果您将一些复杂的对象作为参数传递给函数,您将可能会失去这些对象的所有智能(在函数范围内)。而使用全局对象,则会保留该智能。当你有智能时,它实际上可以缩短调试时间(与其他人所说的相反......)

      我个人觉得这非常有用,而且它肯定在我的代码中占有一席之地。

      (当然,应该始终在局部变量和全局变量之间取得适当的平衡)

      【讨论】:

        【解决方案6】:

        基本上,因为它们可以从页面上的任何脚本访问,并且因为您可以在同一范围内重复它的名称。这就是为什么很多 Javascript 引擎都使用这段代码的原因:

        (function(){
            var foo = 'foo',//Local
            bar = 'bar';//Local
            window.globalVar = foo + bar;//Global
        })();
        alert(foo);//Error
        alert(bar);//Error
        alert(globalVar );//'foobar'
        

        【讨论】:

          【解决方案7】:

          您创建的全局变量可能会覆盖现有的窗口对象属性。因为全局变量是在全局上下文中访问的,即窗口对象。

          【讨论】:

            猜你喜欢
            • 2010-12-06
            • 1970-01-01
            • 2010-10-22
            • 2011-11-20
            • 2014-01-12
            • 2014-11-05
            • 1970-01-01
            • 2010-11-04
            相关资源
            最近更新 更多