在JavaScript中,将方法附加到对象与使用函数的区别

4
在Javascript中,直接或通过原型链将方法附加到对象上非常容易。我使用的许多库都有这种行为。例如AngularJS的$resource库,返回的对象上具有一些神奇的方法,如.$save()和.$delete(),这些方法会触发向服务器发送请求。
然而,在使用Clojure一段时间后,我已经开始喜欢将数据结构传递到函数中以触发行为的方法,并且在我的下一个JavaScript项目中,我考虑尝试以这种风格编写它。
我的问题是,采用这两种编程方式的利弊是什么?
将方法直接附加到对象上(结果通常会在现有对象中进行变异)与将对象作为纯数据结构传递到函数中,在处理后返回新数据结构之间的利弊是什么?
我意识到在AngularJS中,要利用双向绑定,通常需要使用第一种系统,但似乎像React这样的框架可以利用无论是在原地变异还是使用新对象实例的方式。

我认为你需要学习一下面向对象编程的概念,这将有助于解释方法方法的价值。 - Barmar
@RobM. 只有在全局作用域中,function foo(){ } 才会变成 window.foo - Oriol
@Barmar 正如其中一个答案所提到的,JS支持许多不同的编程范式。我对一个不可变的、Lisp风格的程序实现与基于变异的OOP风格之间的权衡感兴趣。 - Samuel
@Samuel 突变是一个独立的问题。由于对象和数组是通过引用传递的,因此您可以在函数调用样式中进行突变。 - Barmar
@Barmar 正确,但我会考虑在JS中使用面向对象的风格,暗示这些方法所附加的对象的变异,而函数调用风格可以修改传入的对象或返回一个新的数据结构。 - Samuel
也许,但是以jQuery为例。它使用面向对象编程风格,但不修改对象。它返回新对象并使用链接。 - Barmar
1个回答

1
非常好的问题。
我会区分“我的类”,也就是我控制的代码和“外部类”,也就是我使用的外部代码,无论是内置的东西还是第三方库。
对于我的代码,我经常更喜欢采用面向对象编程的方式,所以我宁愿使用myObject.doSomething()而不是My.doSomething(object),但这真的取决于情况。
对于“外部”代码,我几乎从不在那里“附加”方法。只有在绝对特殊的情况下才会这样做。我不会用我的方法扩展内置对象和类。我几乎从不将方法注入到外部类和实例中。
这样做的主要原因是兼容性。如果我认为在ForeignClass中添加一些split方法是个好主意,其他人可能会有同样的想法。他们的split可能与我的完全不同。看看AngularJS如何考虑这个问题:他们使用$method命名约定,试图使冲突的可能性更小。
如果你更注重面向对象编程方面,而不是在外部类或对象中注入方法,那么实际上取决于使用情况。不要将编程范例放在实际需求之前。如果你有某些领域,你可能更好地以面向对象方式设计它。反之亦然,如果你只做无状态函数,实际上并没有太多需要实例的地方。
这实际上是JavaScript最好的事情之一——你可以同时实现和使用不同的编程范例而没有任何技术问题。
希望有所帮助。
附注:另一个相关术语是贫血数据模型

谢谢你提供这个贫血数据模型的提示,非常有趣。 - Samuel

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