28.1.4编码惯例
尊重对象所有权
在企业开发中,非常重要的编码惯例就是尊重对象所有权,这意味着不要修改不属于你的对象。简 单来讲,如果你不负责创建和维护某个对象及其构造函数或方法,就不应该对其进行任何修改。更具体 一点说,就是如下惯例。
- 不要给实例或原型添加属性。
- 不要给实例或原型添加方法。
- 不要重定义已有的方法。
为此,最好的方法是永远不要修改不属于你的对象。只有你自己创建的才是你的对象,包括自定义 类型和对象字面量。Array、document 等对象都不是你的,因为在你的代码执行之前它们已经存在了。 可以按如下这样为对象添加新功能。
- 创建包含想要功能的新对象,通过它与别人的对象交互。
- 创建新自定义类型继承本来想要修改的类型,可以给自定义类型添加新功能。
不声明全局变量
最多可以创建一个全局变量,作为其他对象和函数的命名空间。
// 两个全局变量:不要!
var name = "Nicholas";
function sayName() {
console.log(name);
}
以上代码声明了两个全局变量:name 和 sayName()。可以像下面这样把它们包含在一个对象中:
// 一个全局变量:推荐
var MyApplication = {
name: "Nicholas",
sayName: function () {
console.log(this.name);
},
};
这个重写后的版本只声明了一个全局对象 MyApplication。该对象包含了 name 和 sayName()。 这样可以避免之前版本的几个问题。首先,变量 name 会覆盖 window.name 属性,而这可能会影响其 他功能。其次,有助于分清功能都集中在哪里。调用 MyApplication.sayName()从逻辑上会暗示, 出现任何问题都可以在 MyApplication 的代码中找原因。
比如下面的例子: 即使重名它们也只会出现在不同的命名空间中。
// 为另一本书(Professional Ajax)创建命名空间
Wrox.ProAjax = {};
// 添加其他对象
Wrox.ProAjax.EventUtil = { ... };
Wrox.ProAjax.CookieUtil = { ... };
// 可以照常使用 ProJS 下面的对象
Wrox.ProJS.EventUtil.addHandler( ... );
// 以及 ProAjax 下面的对象
Wrox.ProAjax.EventUtil.addHandler( ... );
虽然命名空间需要多写一点代码,但从可维护性角度看,这个代价还是非常值得的。命名空间可以 确保代码与页面上的其他代码互不干扰。
不要比较 null
与 null 进行比较的代码太多了,其中很多因为类型检查不够而频繁引发错误。比如下面的例子:
function sortArray(values) {
if (values != null) {
// 不要这样比较!
values.sort(comparator);
}
}
这个函数的目的是使用给定的比较函数对数组进行排序。为保证函数正常执行,values 参数必须 是数组。但是,if 语句在这里只简单地检查了这个值不是 null。实际上,字符串、数值还有其他很多 值可以通过这里的检查,结果就会导致错误。
现实当中,单纯比较 null 通常是不够的。检查值的类型就要真的检查类型,而不是检查它不能是 什么。例如,在前面的代码中,values 参数应该是数组。为此,应该检查它到底是不是数组,而不是 检查它不是 null。可以像下面这样重写那个函数:
function sortArray(values) {
if (values instanceof Array) {
// 推荐
values.sort(comparator);
}
}
此函数的这个版本可以过滤所有无效的值,根本不需要使用 null。 如果看到比较 null 的代码,可以使用下列某种技术替换它。
- 如果值应该是引用类型,则使用 instanceof 操作符检查其构造函数。
- 如果值应该是原始类型,则使用 typeof 检查其类型。
- 如果希望值是有特定方法名的对象,则使用 typeof 操作符确保对象上存在给定名字的方法。 代码中比较 null 的地方越少,就越容易明确类型检查的目的,从而消除不必要的错误。
使用常量
依赖常量的目标是从应用程序逻辑中分离数据,以便修改数据时不会引发错误。
- 显示在用户界面上的字符串就应该以这种方式提取出来,可以方便实现国际化。
- URL 也应该这样提取出来,因为随着应用程序越来越复杂,URL 极有可能变化。
基本上,像这种地方将来因为某种原因而需要修改时,可能就要找到某个函数并修改其中的代码。每次像这样修改应用程序逻辑,都可能引入新错误。为此,可以把这些可能会修改的数据提取出来,放在单独定义的常量中,以实现数据与逻辑分离。
可以使用以下标准检查哪些数据需要提取。
- 重复出现的值:任何使用超过一次的值都应该提取到常量中,这样可以消除一个值改了而另一 个值没改造成的错误。这里也包括 CSS 的类名。
- 用户界面字符串:任何会显示给用户的字符串都应该提取出来,以方便实现国际化。
- URL:Web 应用程序中资源的地址经常会发生变化,因此建议把所有 URL 集中放在一个地方 管理。
- 任何可能变化的值:任何时候,只要在代码中使用字面值,就问问自己这个值将来是否可能会 变。如果答案是“是”,那么就应该把它提取到常量中。
使用常量是企业级 JavaScript 开发的重要技术,因为它可以让代码更容易维护,同时可以让代码免 受数据变化的影响。