Array 内置了很多方法,但是它无法满足所有用户的需求,这时可以为 Array 对象扩展方法,提高代码重用率。扩展数组的方法一般通过为 Array 对象定义原型方法来实现,这些原型方法能够被所有数组对象继承。

Array.prototype.hello = function(){    //定义Array对象的原型方法
    alert("Hello world");
}

//上面3行代码为数组对象定义了一个原型方法 hello() ,这样就可以在任意一个数组中调用该方法:
var a = [1,2,3];    //定义数组直接量
a.hello();    //调用数组的原型方法,提示"Hello world"

其中 Array 是数组构造函数,prototype 是构造函数的属性,由于该属性指向一个原型对象,然后通过点运算符为其定义属性或方法,这些属性和方法将被构造函数的所有实例对象继承。

下面设计一种安全的、可兼容的数组扩展方法模式:

Array.prototype._m = Array.prototype.m || (Array.prototype.m = function(){
    //扩展方法的具体代码
});
Object.prototype.m = Array.prototype._m

上面代码是一种数组扩展方法的模式,也是通用模式,详细解析如下:

首先,利用判断数组中是否存在名称为 m 的原型方法,如果存在则直接引用该原型方法即可,不再定义,否则定义原型方法 m()。

然后,把定义的原型方法 m() 引用给原型方法 _m(),这样做的目的是,防上当原应方法 m() 引用给 Object 对象的原型时发生死循环调用,可以兼容 Firefox 浏览器。

最后,把数组的临时原型方法 _m(),引用给 Object 对象的原型,这样能够保证所有对象都可以调用这个扩展方法。经过临时原型方法 _m() 中转,就可以防止数组(Array)和对象(Object)都定义了同名方法,如果该方法传递给 Object,而 Object 的原型方法又引用了 Array 的同名原型方法,就会发生循环引用现象。

下面例子,为数组扩展一个所有元素求和的方法,实现代码如下:

Array.prototype._sum = Array.prototype.sum || (Array.prototype.sum = function(){    //检测是否存在同名的方法
    var _n = 0;    //临时汇总变量
    for (var i in this){        //遍历当前数组对象
        if(this[i] = parseFloat(this[i]))    //如果数组元素是数字,则进行累加
            _n += this[i];
    }
    return _n;    //返回累加的和
}
Object.prototype.sum = Array.prototype._sum;    //把数组临时原型方法赋值给对象的原型方法 sum()

该原型方法 sum() 能够计算当前数组中元素为数字的和。在该方法的循环结构体中,首先试图把每元素转换为浮点数,如果转换成功,则把它们相加,转换失败将会返回 NaN,会忽略该元素的值。下面调用该方法:

var a = [1,2,3,4,5,6,7,8,"9"];//定义数组直接量
alert(a.sum));    //返回45

其中第 9 个元素是一个字符串类型的数字,汇总时也被转换为数值进行相加。