为什么闭包比保留变量的全局变量更好?

时间:2010-12-27 00:19:32

标签: javascript closures

我理解JavaScript中的闭包是如何工作的,但我的问题是为什么你会遇到制作闭包以保存变量的所有麻烦?难道你不能让变量全局化吗?或者这会使全局范围变得混乱并使您的代码容易出错。

6 个答案:

答案 0 :(得分:7)

这是一个范围问题。全局变量就是:全局变量,每个人。通过闭合,可以更好地控制变量的范围(可见性),这意味着可以更好地控制可能的非预期副作用。

http://en.wikipedia.org/wiki/Global_variable

  

[Globals]通常被认为是不良行为,正是因为它们的非本地性:全球化   变量可以从任何地方修改(除非它们驻留在受保护的内存中),   程序的任何部分都可能依赖于它。因此全局变量具有   创建相互依赖关系和添加相互依赖关系的无限潜力   增加复杂性。见action at a distance

答案 1 :(得分:3)

两个字:种族条件

如果在全局范围内设置变量,而其预期用途是 function 实例的本地变量,则存在两个(或更多)唯一实例访问和操作此全局变量并具有此风险的风险所有实例都表现得不可预测。

还有很多其他原因可以解释为什么要在全局空间中存储本地状态时要非常小心。

其中一个将重新使用设置此变量的最后一个实例的状态(如果您没有同时激活多个实例)。

还可能与依赖于具有相同名称的全局变量的其他代码片段冲突。

从审美角度来说,你也将全局命名空间变成一团糟(那里有很多随机变量,没有任何直接的信息,说明它们为什么会在那里出现)。

将变量放入全局空间容易出错,并使运行时视图变得混乱。 JS的范围可能性也使它变得不必要,这就是为什么没有人这样做(除了真正属于那里的东西)。

作为补充评论,请不要在未来的问题中提及您的年龄或吹嘘您的编码能力。这与问题无关。

答案 2 :(得分:2)

在JavaScript中只有一个全局命名空间,因此在同一页面上使用不同的Frameworks / Toolkits非常困难,因为变量名称迟早会开始发生冲突。 / p>

闭包也提供了一种模拟私有变量的方法:

function Counter(start) {
   var count = start;
   return {
       increment: function() {
           count++;
       },

       get: function() {
           return count; // only gives you the value, but no write access
       }
   }
}

但这是一个相当“愚蠢”的例子,当涉及各种类型的回调时,闭包特别有用,你不想管理为每个回调保存数据的全局数组,它很简单,更清晰闭包。

对于闭包的极端使用,请查看JavaScript的implementation类。 (免责声明,代码由我撰写。)

这里proto跟踪每个类的原始属性,但它仍然可供extend使用,然后可以将这些属性从其他类继承后添加到其他类中。

答案 3 :(得分:1)

其中一个原因是防止全球污染。另一种方法是通过更改传递的值来对许多操作使用相同的实现。

js> makeadd = function(num) { return function(val) { return num+val } }
function (num) {
    return function (val) {return num + val;};
}
js> add3 = makeadd(3)
function (val) {
    return num + val;
}
js> add4 = makeadd(4)
function (val) {
    return num + val;
}
js> add3(add4(2))
9

答案 4 :(得分:1)

其他人已经提到过golbal name pollution和global is evil,甚至是OP:

  
    

或者那会使全球范围变得混乱......

  

但还有另一个原因。

全局变量只有一个实例。这使得它不能很好地扩展。如果将来某个时候您需要多个对象实例,您将需要创建第二个全局变量或将原始变量转换为数组并手动管理该数组(即自行决定何时删除该对象)来自记忆)。

如果它已经由闭包创建,则可以通过一次又一次地调用创建闭包的函数来简单地创建第二个,第三个和第四个实例。您还可以获得额外的好处,即所有创建的实例在不再需要时会自动进行垃圾回收。

这种情况比你想象的更频繁。想象一下,你刚刚创建了一个动画序列,动画文本可以淡入淡出。并且您已使用全局变量来跟踪动画的某些状态。而且你认为那很好,一切都好,忘了它。然后一段时间后,你的老板来找你,说他喜欢动画,并希望将它添加到页面中的其他内容。现在你必须同时处理多个动画,并且需要将全局转换为一个数组,以防止一个动画破坏另一个正在进行的动画......如果它们只是封装在闭包中开始......


你知道吗,就像我在提交这个答案后向下滚动一样,我发现了一个问题,说明了全局变量的问题:How do you create multiple timers on one page that operate independently -- javascript?。虽然对于那个特定的问题,你并不需要一个闭包,只是普通的局部变量。

答案 5 :(得分:1)

离开家时,最好把钥匙交给邻居,以便你的配偶可以收集它,以防他/她早点回家,但是把它丢在路上并不是一个好主意。

相关问题