Prototype Class对象学习_Javascript教程-查字典教程网
Prototype Class对象学习
Prototype Class对象学习
发布时间:2016-12-30 来源:查字典编辑
摘要:复制代码代码如下:/*BasedonAlexArnell'sinheritanceimplementation.*/varClass=(fu...

复制代码 代码如下:

/* Based on Alex Arnell's inheritance implementation. */

var Class = (function() {

//临时存储parent的prototype

function subclass() {};

//创建类的方法

function create() {

var parent = null, properties = $A(arguments);

//检查新建一个类时,是否指定了一个父对象

//如果指定了父类,赋值给parent

if (Object.isFunction(properties[0]))

parent = properties.shift();

//真正用作返回的类,在创建实例时,将调用initialize方法进行初始化

function klass() {

this.initialize.apply(this, arguments);

}

//给klass添加addMethods方法,在调用create方法之后

//仍可以调用addMethods方法进行类级别的方法扩充

Object.extend(klass, Class.Methods);

//给返回的类添加两个属性,superclass:父类,subclasses:子类的集合

klass.superclass = parent;

klass.subclasses = [];

//如果创建类时指定了父对象,则把klass的原型指向父对象的实例,实现原型链继承

if (parent) {

subclass.prototype = parent.prototype;

klass.prototype = new subclass;

//为父类添加子类,维护父类的子类集合

parent.subclasses.push(klass);

}

//向新类添加方法

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

klass.addMethods(properties[i]);

//如果没有指定初始化方法,则默认把一个空方法赋给初始化方法

if (!klass.prototype.initialize)

klass.prototype.initialize = Prototype.emptyFunction;

/*

* 修正新类的构造函数,使得构造函数指向自己,这里特意说一下(如果注释掉下面这行):

* var Person=Class.create();

* var p1=new Person();

* alert(p1.constructor==Person) //true

* var Man=Class.create(Person)

* var m1=new Man();

* alert(m1.constrcutor==Man) //false

* alert(m1.constrcutor==Person) //true

* alert(m1.construcctor==p1.constrcutor) //true

*

* 看出问题来了吧?Man的构造函数竟然指向了Person的构造函数

* 问题的根源在klass.prototype = new subclass;这句话

* 具体原因我就不解释了,要详细理解的请查看《JavaScript语言精髓与编程实践》155~160页

*/

klass.prototype.constructor = klass;

return klass;

}

//把创建类时的方法添加到新类,或者在创建完类之后在添加类级别的方法

function addMethods(source) {

//取得新类的父类

var ancestor = this.superclass && this.superclass.prototype;

var properties = Object.keys(source);

//貌似下面的判断总是为真,不知道为什么这么写,知道的告诉我?

if (!Object.keys({ toString: true }).length) {

//如果新类重写了toString和valueOf方法则添加之

if (source.toString != Object.prototype.toString)

properties.push("toString");

if (source.valueOf != Object.prototype.valueOf)

properties.push("valueOf");

}

//遍历所有的新类声明中的方法

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

//property是函数名称,value是函数体

var property = properties[i], value = source[property];

//判断这个方法是否需要调用父类的同名方法

if (ancestor && Object.isFunction(value) &&

value.argumentNames().first() == "$super") {

var method = value;

//这里很重要!

//替换$super参数,使得这个参数指向父类的同名方法

//这里应用了Function的wrap方法,wrap方法的解释请参考【Prototype 学习——Function对象】

//method是新定义的方法,所以他的第一个参数为$super,然后从'='到'.'之间返回的是父类的同名方法

//最后调用wrap方法把$super参数替换成父类的同名方法,这样在子类调用$super()时,将调用父类的同名方法

//这里构造的非常棒!值得思考

value = (function(m) {

return function() { return ancestor[m].apply(this, arguments); };

})(property).wrap(method);

//将新产生的value(即经过修改过的子类方法)的valueOf和toString指向原子类的同名方法

//这里是在修正调用wrap方法之后的遗留问题

value.valueOf = method.valueOf.bind(method);

value.toString = method.toString.bind(method);

}

//把方法添加到新类中

this.prototype[property] = value;

}

return this;

}

//返回Class的可调用方法

return {

create: create,

Methods: {

addMethods: addMethods

}

};

})();

这个类就提供了2个方法:create和addMethods,上面的源码注释中已经说明的很清楚了,下面就看些例子,具体说明一下用法:

复制代码 代码如下:

//声明Person类,并定义初始化方法

var Person = Class.create({

initialize: function(name) {

this.name = name;

},

say: function(message) {

return this.name + ': ' + message;

}

});

// when subclassing, specify the class you want to inherit from

var Pirate = Class.create(Person, {

// redefine the speak method

//注意这里的$super用法,在对照源码中的解释仔细看一下

say: function($super, message) {

return $super(message) + ', yarr!';

}

});

var john = new Pirate('Long John');

john.say('ahoy matey');

// -> "Long John: ahoy matey, yarr!"

复制代码 代码如下:

var john = new Pirate('Long John');

john.sleep();

// -> ERROR: sleep is not a method

// every person should be able to sleep, not just pirates!

//这里是addMethods的用法,可以在类级别扩充方法

Person.addMethods({

sleep: function() {

return this.say('ZzZ');

}

});

john.sleep();

复制代码 代码如下:

//这里是superclass和subclasses两个属性的用法

Person.superclass

// -> null

Person.subclasses.length

// -> 1

Person.subclasses.first() == Pirate

// -> true

Pirate.superclass == Person

// -> true

三个例子几本覆盖了Class类的方法,详细例子请参考:http://prototypejs.org/learn/class-inheritance

相关阅读
推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
  • 大家都在看
  • 小编推荐
  • 猜你喜欢
  • 最新Javascript教程学习
    热门Javascript教程学习
    编程开发子分类