将全局变量传递给函数有价值吗?

4

我最近看到的代码长这样:

(function (someGlobal) {
    someGlobal.DoSomething();
})(someGlobal);

这里的someGlobal是一个大型框架类,可能是JQuery。这样做有什么好处?这是一个好的做法吗?似乎这段代码等效且更少出错,因为你没有隐藏全局变量:

(function () {
    someGlobal.DoSomething();
})();
4个回答

2
  • 如果全局引用被覆盖,您可以使用可靠的本地引用

  • 它缩短了访问作用域链的长度


"It seems like this code would be equivalent and less error prone because you don't hide the global:"

(function () {
    someGlobal.DoSomething();
})();
如果您预计全局变量会被覆盖,并且您的代码依赖于被覆盖的值,那么您肯定不希望在函数中使用本地变量来屏蔽它。
除此之外,在函数中的本地引用不应更容易出现错误。

1
  1. 只有在您确定代码将在全局变量被覆盖之前执行时才能这样做。
  2. 只能通过一个作用域对象实现,因此收益非常小(因为编译器可能会在函数实例化时优化作用域链)。因此,好处相当小。
- RobG
@RobG:1. 如果它不是首先执行,那么就有问题需要解决。我们也可以说“只有在你确定全局变量一开始就存在的情况下”,但那就没有意义了,对吧?如果全局变量被覆盖,那么IIFE的问题就无关紧要了。2. 是的,有一点点性能提升。 - user1106925
1
旨在运行在可能被重新分配的全局变量环境中的代码,很可能也处于一个不知道它是否会在可能执行该重新分配的代码之前或之后运行的环境中。在这种情况下,传递一个全局变量并不能提供任何确定性,即它还没有被重新分配。毕竟,这不就是全局变量的意义所在吗? - RobG

1

如果它是全局变量,为什么要传递呢?直接将其用作全局变量即可。

然而,这似乎可以作为一种有效的过渡机制来消除全局变量。例如,如果我继承了一个有很多全局变量的大型代码库,一个潜在的过渡机制就是逐步消除全局变量的使用方式。这种改变可以通过最小的差异逐步完成。


0

这样你就可以在安全的作用域中使用别名。

(function ($) {
    $.DoSomething();
})(someGlobal);

更新:

最重要的是,这种方式为您定义了一个安全范围,以便您使用someGlobal

如果您使用第二种方法,someGlobal仍然是全局变量,想象一下您在回调函数中使用someGlobal,并在外部某处覆盖了someGlobal,会发生什么?


这将是一个好处,但在这种情况下,他们使用了完全相同的名称。 - Steve Rowe
@SteveRowe 是的,除此之外,更重要的是为您使用 someGlobal 定义一个安全范围。 - xdazz
在这里尝试理解。如果该函数仅被调用一次(注意引用未被捕获且为匿名),那么安全作用域是否有帮助?即使它被多次调用,是否真的存在像JQuery/$这样的东西被覆盖的危险? - Steve Rowe
@SteveRowe 是的,someGlobal 就是你传递给它的 someGlobal - xdazz
但为什么在调用时间和执行时间时,someGlobal 的解析结果会不同呢?这两者应该几乎同时进行。 - Steve Rowe

0

好处是,在该函数内,someGlobal 是明确无误的。


它如何比将其作为参数传递更不含糊?如果您不知道函数中的全局变量是什么,您也不会知道调用站点的全局变量是什么。 - Steve Rowe
@SteveRowe,这种模式在更广泛的场景中更有用,其中调用站点与函数声明“远离”,并涉及闭包。正如其他人所说,someGlobal可能会在函数开始和使用之间的中途发生变化。从函数内部代码的角度来看,参数值(或传递的参数引用)不会改变。 - Humberto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接