面向对象的JavaScript最佳实践?

253

我正在使用JavaScript编写一个大项目。 我记得上一个项目非常艰难,因为JS的hacky代码很快就会变得难以阅读,而我希望这段代码很干净。

嗯,我正在使用对象构建库,但在JS中有几种定义事物的方式,这意味着在作用域、内存管理、命名空间等方面有重要的后果。例如:

  • 是否使用var
  • 在文件中定义还是使用(function(){...})()(像Jquery一样)
  • 是否使用this
  • 使用function myname() 还是 myname = function()
  • 在对象主体中定义方法还是使用“prototype”
  • 等等

那么,在JS中进行面向对象编程时,真正的最佳实践是什么?

这里真正期望学术解释。欢迎提供书籍链接,只要它们涉及质量和稳健性。

编辑:

我已经读了一些文章,但我仍然对上述问题和任何最佳实践非常感兴趣。


2
也许标题中的“面向对象”应该替换为“现代”。 - viam0Zah
43
为什么这篇帖子会被标记为“不具建设性”,明明有79个赞、82个收藏和91个回答的赞同...? - Brett Rossier
14
这种类型的问题经常被关闭。我理解关闭的原因,但因为这些问题很重要,而且总是受到欢迎(而且当我有类似问题时总能找到它们),所以我想知道是否有人可以将我们引导到适当的场所来提出这些问题? - K. P. MacGregor
1
说真的,如果不是为了回答问题或提供指引,这个网站存在的意义是什么?SE需要具体解释为什么关闭一个问题,并且不能只用模板化的语言来回答。 - lonstar
2
@BrettRossier 如果你不运用它,权力有何用处?SO是民主排序如何运作的现场演示。肯定有一些心理学家正在研究它... - user1115652
显示剩余5条评论
6个回答

289

使用`var`还是不使用

您应该使用 var 语句来声明变量,否则它会进入全局作用域。

值得一提的是,在严格模式下("use strict";),未声明的变量分配会抛出 ReferenceError

目前 JavaScript 没有块级作用域。Crockford 学派教你在函数体的开头放置 var 语句,而 Dojo 的风格指南则建议在最小的作用域中声明所有变量。(JavaScript 1.7 中引入的 let 语句和定义 不是 ECMAScript 标准的一部分。)

将经常使用的对象属性绑定到局部变量中是一个好习惯,因为这比查找整个作用域链要快。 (请参见优化 JavaScript 以获得极致性能和低内存消耗。)

在文件中定义还是在`(function(){...})()` 中定义

如果你不需要在代码外部访问对象,可以将整个代码包装在一个函数表达式中,这被称为模块模式。它具有性能优势,并且还允许您的代码在高层次上进行缩小和混淆。您还可以确保它不会污染全局命名空间。 在JavaScript中包装函数 还允许您添加面向方面的行为。Ben Cherry有一篇 模块模式详解 的文章。

使用 `this` 还是不用

如果你在JavaScript中使用伪类继承,你几乎无法避免使用this。使用哪种继承模式只是一种口味问题。在其他情况下,请查看Peter Michaux关于在JavaScript中创建没有"this"的小工具的文章。

使用`function myname()` 还是 `myname = function();`

function myname()是一个函数声明,而myname = function();是分配给变量myname的函数表达式。后者形式表示函数是一等对象,你可以像处理变量一样对待它们。它们之间唯一的区别是所有函数声明都被提升到作用域的顶部,在某些情况下可能很重要。否则它们是相等的。function foo()是一种简写方式。有关提升的更多细节,请参见JavaScript作用域和提升文章。

在对象体中定义方法或使用“prototype”

由你决定。JavaScript有四个对象创建模式:伪经典、原型、函数和部件(Crockford,2008)。每种模式都有其利弊,请参见Crockford的视频讲座或获取他的书籍The Good Parts,如Anon已建议

框架

我建议您选择一些JavaScript框架,学习它们的惯例和风格,找到最适合您的那些实践和模式。例如,Dojo Toolkit提供了一个强大的框架,用于编写面向对象的JavaScript代码,甚至支持多重继承。

模式

最后,有一个专门致力于探索常见的JavaScript模式和反模式的博客。还要查看Stack Overflow中的问题JavaScript是否有任何编码标准?


1
JavaScript 有四种对象创建模式:伪经典、原型、函数式和部件。这里简要介绍一下它们的优缺点。 - BadHorsie
2
“let”语句和定义是JavaScript 1.7引入的,不是ECMAScript标准的一部分。现在它已成为ES6的一部分。 - Michał Perłakowski

13

我会写下一些自己读过或者在实践中应用的东西,以便让阅读这篇问题的人不会感到沮丧,因为大部分答案都是伪装成RTMF(读取手册)的回答(即使我必须承认,推荐的书籍确实很好)。

变量使用

在JavaScript中,任何变量都应该已经在更高层次的作用域中声明。因此,在需要一个新变量时,请先声明它,以避免意外操作全局变量而不知情。 因此,请始终使用var关键字。

在对象中制作变量私有化,请使用this.my_var = my_value来声明公共变量。

声明方法

在JS中,有多种声明方法的方式。对于面向对象编程人员来说,最自然且高效的方式是使用以下语法:

在对象主体内

this.methodName = function(param) {

/* bla */

};

有一个缺点:由于有趣的JS作用域,内部函数将无法访问“this”。Douglas Crockford建议使用传统的本地变量“that”来绕过此限制。因此它变成了:

function MyObject() {

    var that = this;

    this.myMethod = function() {

        jQuery.doSomethingCrazy(that.callbackMethod);

    };

};

不要依赖自动换行符

如果你忘记在代码行末尾添加分号;,JS会尝试自动添加它。但是不要依赖这种行为,因为你将面临难以调试的错误。


8

5

5
我经常感觉自己是这里唯一使用MooTools进行javascript编程的人。
它代表着我的面向对象工具,即mootools。
我真的很喜欢他们在javascript中面向对象编程的方式。你可以使用他们的类实现以及jquery,所以你不必放弃jquery(尽管mootools同样做得很好)。
无论如何,请仔细阅读第一个链接并看看您的想法,第二个链接是关于mootools文档的。 MooTools & Inheritance MooTools Classes

我认为试图弯曲一种编程语言以适应您旧有的习惯并不是一件好事。就像使用 # 来替换使其看起来像 FORTRAN 等等的 C 语言人们一样。我认为你应该尝试学习语言的工作方式(以及最佳实践),并以不太打扰你的方式使用它。但是不要真的改变它。 - Bite code
2
我认为 MooTools 对象系统非常优雅,能够真正帮助我保持代码的组织/封装。 - awesomo

0
这是一本涵盖大部分基础知识的书籍:
《面向对象的JavaScript:高质量应用程序和库》{{link1}}

谢谢,但我不是在寻找基础知识。我能编写(糟糕的)可运行JS代码。或者至少大部分时间可以 :-) 我需要指导来编写相同的代码,但正确地编写。 - Bite code

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