编程实践

书写可维护的JavaScript并不仅仅是关于如何格式化代码,它还关系到代码做什么问题。

尊重对象所有权

你不能修改不属于你的对象。JavaScript的动态性质使得几乎任何东西在任何时间都可以修改。如果你不负责维护某个对象,它的对象或者它的方法,那么你就不能对它们进行修改。更具体所:

  • 不要为实例或原型添加属性
  • 不要为实例或原型添加方法
  • 不要重定义已存在的方法

依然可以通过以下方式为对象创建新的功能:

  • 创建包含所需功能的新对象,并用它与相关对象进行交互。
  • 创建自定义类型,继承需要进行修改的类型。然后可以为自定义类型添加额外功能。

避免全局量

尽可能避免全局变量和函数,这也关系到创建一个脚本执行的一致的和可维护的环境。最多创建一个全局变量,让其他对象和函数存在其中。请看以下例子:

//两个全局变量——避免
var name = "Nicholas";
function sayName() {
    alert(name);
}

这段代码包含了两个全局量:变量name和函数sayName()。其实可以创建一个包含两者的对象。

//一个全局量——推荐
var MyApplocation = {
    name: "Nicholas",
    sayName: function() {
        alert(this.name);
    }
};

这段重写的代码引入了一个单一的全局变量MyApplication,name和sayName()都附加到其上。

这样做消除了一些存在于前一段代码中的一些问题。

首先,变量name覆盖window.name属性,可能会与其他功能产生冲突;

其次,它有助于消除功能作用域的混淆。调用MyApplocation.sayName()在逻辑上暗示代码的任何问题都可以通过检查定义的MyApplocation()代码来确定。

单一的全局量的延伸便是命名空间的概念。命名空间包括创建一个用于放置功能的对象。

YUI库有若干追加功能的命名空间。比如:
- YAHOO.util.Dom——处理DOM的方法
- YAHOO.util.Event——与事件交互的方法
- YAHOO.lang——用于底层语言特性的方法

对于YUI,单一的全局对象YAHOO作为一个容器,其中定义了其他对象,用这种方式将功能组合在一起的对象,叫做命名空间。

避免与null进行比较

开发人员需要自己进行类型检查。

不充分的类型检查导致错误.

function sortArray(values) {
    if (values != null) {    //避免!
        values.sort(comparator);
    }
}

values阐述应该是一个数组,应该检查它是不是一个数组而不是检查是否非null。函数按照下面的方式修改会更加合适。

function sortArray(values) {
    if (values instanceof Array) {    //推荐
        values.sort(comparator);
    }
}

如果看到了与null比较的代码,尝试使用以下技术替换:

  • 如果值应为一个引用类型,使用instanceof操作符检查其构造函数
  • 如果值应为一个基本类型,使用typeof检查其类型
  • 如果是希望对象包含某个特定的方法名,则使用typeof操作符确保指定名字的方法存在于对象上。

代码中的null比较越少,就越容易确定代码的母的,并消除不必要的错误。

使用常量

尽管JavaScript没有常量的正式概念,但它还是很有用的。这种将数据从应用逻辑分离出来的思想,可以在不冒引入错误的风险的同时,就改变数据。请看以下例子:

function validate(value) {
    if (!value) {
        alert("Invalid value!");
        location.href = "/error/invalid.php";
    }
}

这个函数中有两端数据:要显示给用户的信息以及URL。

显示在用户界面上的字符串和URL应该抽取出来,以便于在修改这些数据时就不需要找到函数并修改其中的代码了。

可以通过将数据抽取出来变成单独定义的常量的方式,将应用逻辑与数据修改隔离开来。

var Constants = {
    INVALID_VALUE_MSG: "Invalid value!",
    INVALID_VALUE_URL: "/errors/invalid.php"
};

function validate(value) {
    if (!value) {
        alert(Constants.INVALID_VALUE_MSG);
        location.href = Constants.INVALID_VALUE_URL;
    }
}

关键在于将数据和使用它的逻辑进行分离。要注意的值的类型如下所示:
- 重复值——任何在多处用到的值都应该抽取为一个常量。这也包含CSS类名。
- 用户界面字符串——任何用于显示给用户的字符串,都应该被抽取出来以方便管理.
- URLs——在Web应用中,资源位置很容易变更,所以推荐用一个公共地方存放所有的URL
- 任意可能会改变的值——每当你在用到字面量值的时候,都要问一下自己这个值在未来是不是会发生变化。如果答案是”是“,那么这个值就应该被提取出来作为一个常量。

Loading Disqus comments...
Table of Contents