Prototype Class对象学习

代码如下:

/* 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

(0)

相关推荐

  • Prototype Selector对象学习

    复制代码 代码如下: function $$() { return Selector.findChildElements(document, $A(arguments)); } 这个类可以分成三个部分:第一个部分就是根据不同的浏览器,判断使用什么DOM操作方法.其中操作IE就是用普通的getElementBy* 系列方法:FF是document.evaluate:Opera和Safari是selectorsAPI.第二部分是对外提供的基本函数,像findElements,match等,Eleme

  • Prototype Enumerable对象 学习第1/2页

    Enumerable provides a large set of useful methods for enumerations, that is, objects that act as collections of values. It is a cornerstone of Prototype. Enumerable is what we like to call a module: a consistent set of methods intended not for indepe

  • Prototype ObjectRange对象学习

    Ranges represent an interval of values. The value type just needs to be "compatible," that is, to implement a succ method letting us step from one value to the next (its successor). Prototype provides such a method for Number and String, but you

  • Prototype Class对象学习

    复制代码 代码如下: /* Based on Alex Arnell's inheritance implementation. */ var Class = (function() { //临时存储parent的prototype function subclass() {}; //创建类的方法 function create() { var parent = null, properties = $A(arguments);     //检查新建一个类时,是否指定了一个父对象     //如

  • Prototype Object对象 学习

    Object is used by Prototype as a namespace; that is, it just keeps a few new methods together, which are intended for namespaced access (i.e. starting with "Object."). 上面说的namespace个人理解就相当于C#中的静态类,提供工具函数的意思,和C#中的namespace应该不是一个概念.因为C#中的命名空间后面不会直

  • Prototype Hash对象 学习

    复制代码 代码如下: //Hash对象的工具函数 function $H(object) { return new Hash(object); }; var Hash = Class.create(Enumerable, (function() { //初始化,创建一个新的Hash对象 function initialize(object) { this._object = Object.isHash(object) ? object.toObject() : Object.clone(obje

  • Prototype Array对象 学习

    复制代码 代码如下: Array.from = $A; (function() { //Array原型的引用     var arrayProto = Array.prototype, slice = arrayProto.slice,      //JS 1.6里面会有原生的forEach方法 _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available function each(it

  • Prototype String对象 学习

    复制代码 代码如下: //String对象的静态方法 Object.extend(String, { interpret: function(value) { return value == null ? '' : String(value); }, specialChar: { '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '\\': '\\\\' } }); Object.extend(String.prot

  • Prototype Template对象 学习

    复制代码 代码如下: var Template = Class.create({ //初始化方法 initialize: function(template, pattern) { this.template = template.toString(); this.pattern = pattern || Template.Pattern; }, //格式化方法,如果从java的角度来说,其实叫format更好 :) evaluate: function(object) {     //检查是否

  • Prototype Function对象 学习

    这个对象就是对function的一些扩充,最重要的当属bind方法,prototype的帮助文档上特意说了一句话:Prototype takes issue with only one aspect of functions: binding.其中wrap方法也很重要,在类继承机制里面就是利用wrap方法来调用父类的同名方法.argumentNames bind bindAsEventListener curry defer delay methodize wrap 复制代码 代码如下: //通

随机推荐