ECMAScript5面向类的编程探讨

基于代码优雅和简洁的考虑,本人一直在探究如何在es5里面写出类似于Java那样面向对象的代码,下面是一些代码与大家分享一下,里面有详细的注释说明,如有疑问,可以评论区留言。

在函数原型绑定一个方法,工具函数

/*

  • 在函数原型里绑定方法

  • */

Function.prototype.method = function (name, func) {

if (!this.prototype.hasOwnProperty(name)) {

this.prototype[name] = func;

}

};

工具函数,对象继承,在后面的类式继承里使用

/*

*工具函数:对象继承

*@param son:表示儿子对象

*@param parent:表示父亲对象

*@return 新的儿子对象

*/

function extend(son,parent)

{

/*为了让新对象复制儿子对象中已有的属性,我们需要改造son

*使其具有这种形式:{a:属性描述符对象,b:属性描述符对象}

*注意
Object.getOwnPropertyNames(son)返回所有自有(非继承)属性,包括不可枚举的

*/

var names = Object.getOwnPropertyNames(son);

var obj={};//复制son的临时对象

for (var i = 0; i < names.length; i++) {

obj[names[i]]=Object.getOwnPropertyDescriptor(son, names[i]);

}

//创建新的对象,以parent作为原型

return Object.create(parent,obj);

}

类式继承,参数可以是对象或者构造函数,对象表示一个接口

/*

  • 定义:extend,用于类继承

  • 参数:父类型,可以是对象或者构造函数

  • 返回值:升级版的子类,比如:A'=A.extend(B);

  • */

Function.prototype.extend = function (parent) {

if(this._super)

{

throw new Error("超类已经存在,不可重复继承!");

}

var Parent = parent || Object;

//父类是个object

if(typeof Parent==="object")

{

//临时函数

var F=function(){};

F.prototype=Parent;

F.prototype.constructor=F;

Parent=F;

}

if (typeof Parent === 'function') {

//生成升级版的子类构造函数

var prototype=extend(this.prototype,Parent.prototype);

//保存父类的原型

Object.defineProperty(this,"_super",{

value:Parent.prototype,

writable:true,

enumerable:false,

configurable:false

});

//修改原型的constructor属性,为Child

prototype.constructor = this;

this.prototype = prototype;

return this;

} else {

throw new TypeError('参数:' + p + '类型不合法!');

}

};

测试代码如下:

var Person=function(name){

this.name=name;

Person.method("getName",function(){return this.name;});

};

注意:原型方法的定义在构造函数里面。这样会导致原型方法延迟绑定,也就是在实例化的时候才能绑定到原型中。

var Student=function Student(name,age){

/*这里会自动调用Person的构造函数,等同于:Person.call(this,name),缺陷是要保证参数的正确顺序

*/

this.age=age;

Student.method("getAge",function(){return this.age;});

}.extend(Person);

//实例化

new Student("张三",34).getName();

new Person("李四").getName();

这种风格的代码优点有如下几条
1,简洁优雅。
2,原型方法直到实例化时才绑定到原型,当然,也可以按常规的方式在构造函数外面定义,继承调用前和调用后都可以。
3,如果把原型方法定义放在构造函数里面,整个类的定义更紧凑,都在一对花括号里面。
4,可以继承接口,父类如果是对象,可以视为一个无构造函数的抽象接口。
5,构造函数调用时先调用父类构造函数。

posted @ 2022-04-08 10:10  江金汉  阅读(83)  评论(0编辑  收藏  举报