详解JavaScript中类的扩充

作者:admin     字体:[增加 减小]    类型:原创
在PHP语言中一旦写好类,那么在后面的代码中是不可动态修改的。但是JavaScript基于原型的继承机制却是动态的,意即创建对象之后原型属性改变也会影响到所有实例对象。

JavaScript中基于原型的继承机制是动态的:对象从其原型继承属性,如果创建对象之后原型的属性发生改变,也会影响到继承这个原型的所有实例对象。这意味着我们可以通过原型对象添加新方法来扩充JavaScript类。

JavaScript内置类的原型对象也是一样如此“开放”,也就是说可以给数字、字符串、数组、函数、对象等数据类型添加方法。

//多次调用这个函数f,传入一个迭代数
//比如,要输出"hello"三次
Number.prototype.times = function(f,context){
    var n = Number(this);
    for(var i=1;i<=n;i++ ) f.call(context,i);
}

//定义一个整数
var n = 3;
n.times(function(n){
    console.log(n+"hello"); //将hello输出三遍
});

//如果不存在ES5的String.trim()方法的话,就定义它
String.prototype.trim = String.prototype.trim || function(){
    if(!this) return this;  //空字符串不做处理
    return this.replace(/^\s+|\s+$/g,"");   //使用正则表达式将首尾空格替换
}


function quacks (){};

//返回函数的名字,如果它有(非标签的)name属性,则直接使用name属性
//否则,将函数转换为字符串然后从中提取名字
//如果是没有名字的函数,则返回一个空字符串
Function.prototype.getName = function() {
    return this.name || this.toString().match(/function\s*([^()]*)\(/)[1];
}

可以给Object.prototype添加方法,从而使所有的对象都可以调用这些方法。但这种做法并不推荐,因为在ES5之前,无法将这些新增的方法设置为不可枚举的,如果给Object.prototype添加属性,这些属性是可以被for/in循环遍历到的。

然而并不是所有的宿主环境(比如Web浏览器)都可以使用Object.defineProperty(),这跟ECMAScript的具体实现有关。比如,在很多浏览器中,可以给HTML.Element.prototype添加方法,这样当前文档中表示HTML标记的所有对象就可以继承这些方法。但当前版本的IE则不支持这样做。