JavaScript - 将函数存储在对象中 - 是不好的实践吗?

77

将函数存储在对象中而不是全局定义它们(从而使其全局可用),这是否被认为是不良的编码实践?

考虑以下:

1.

Foo = {
    bar: function() {
        alert("baz");
    }   
}

Foo.bar();

对比

2.

function bar() {
    alert("baz");
}

bar();

虽然第二个例子的代码可能会略微减少,但当您开始有大量函数时,就会变得混乱。我发现使用Game.update()而不是使用updateGame()或类似方法要更加简洁清晰。当您深入了解时,例如Game.notify.admin(id)等,它可以让您的代码更加优美。

将函数存储在对象中是否有任何缺点?


2
不可能。如果有这样的问题,那么全球拥有数百万用户的框架就不会这样做了。 - Jon
2
不,这是标准的命名空间,以避免全局污染,正如你的问题已经指出的那样。为什么会有问题呢? - user1106925
3个回答

80

推荐使用第一种方法。这样你可以明确定义函数的作用域,而不是污染全局作用域。使用第一种方法没有任何缺点,只有好处 :-)

结论:总是使用第一种方法来定义函数。第二种方法就像 90 年代的 JavaScript,让它在过去安息,并使用正确的作用域。


3
过度嵌套存在一些不利之处。举例来说,将_函数_放在对象上“因为这样更好”是愚蠢的。(将函数放在全局范围内也很愚蠢,但我们处理的不是这个,假设是模块范围)。此外,将对象和函数嵌套超过4层深会变得愚蠢。理想情况下,您希望您的对象/方法链具有1或2个层级,foo.bar.baz() - Raynos
2
这真的与作用域有关吗?还是只是为了减少全局变量的数量,以降低重复变量名称的可能性。"全局污染"是否有任何其他不良副作用? - RobG
@Raynos - 是的,我在我的回答中指出了这一点,但是“污染全局范围”的说法被过度使用了。 - RobG
1
@RobG,这不是关于冲突的问题,而是确保代码不能通过破坏全局状态无意中破坏不变量。在大型项目中,您只需要避免使用全局状态,而不是依赖于全局状态未被破坏的约定。 - Raynos
2
@PhilOlson——仅在对象中存储值与使用变量相比没有任何好处。如果需要模块化(而模块化是一个好主意),那么就有模块模式,它仅公开需要公开的属性,并将其余部分隐藏在单独的执行上下文中。 - RobG
显示剩余3条评论

5

命名空间对象并没有什么神奇的地方,如果您使用了大量全局变量也不一定会出现任何问题。使用“命名空间”对象的主要原因是减少重复的全局变量名称。第二个原因是为了方便起见将类似的函数分组在一起,例如:

// Object example (suggested best practice):
// DOM functions are under myLib.dom
myLib.dom.someDOMFunction0;
myLib.dom.someDOMFunction1;

// Utility functions are under myLib.util
myLib.util.someUtilityFunction0;
myLib.util.someUtilityFunction1;

请注意,上述内容与类似的全局变量几乎具有相同的重复机会:
// Global variable example:
myLib_dom_someDOMFunction0;
myLib_dom_someDOMFunction1;

myLib_util_someUtilityFunction0;
myLib_util_someUtilityFunction1;

当然,前者通常更受欢迎,因为它被认为更易于使用。我并不主张采用第二种方法(我使用第一种方法),只是指出,虽然创建大量全局变量存在问题,但所谓的“全局命名空间污染”作为危害被高度夸大了。


4

在这个特定的情况下,使用第一种方法。但是如果你的Foo对象变得非常复杂,你可能需要采用另一种方法,这将给你使用构造函数的机会。而且,当涉及到函数的作用域时,第一种方法有时并不是最好的选择:

function Foo(appName){
    this.name = appName;      
}

Foo.prototype.Bar = function(){
   alert(this.name)
}

var a = new Foo("baz");
a.Bar();

检测到反模式。请使用原型,谢谢。 - Raynos
你是对的 @Raynos,将函数声明在另一个函数内部的问题在于每次初始化类时都会重新创建它。 - Karl Mendes

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