Prototype Class对象学习


Posted in Javascript onJuly 19, 2009
/* 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 相关文章推荐
[原创]静态页面也可以实现预览 列表不同的显示方式
Oct 14 Javascript
轻轻松松学习JavaScript
Feb 25 Javascript
js Function类型
Dec 04 Javascript
jquery下拉select控件操作方法分享(jquery操作select)
Mar 25 Javascript
详谈javascript中DOM的基本属性
Feb 26 Javascript
深入理解JavaScript系列(28):设计模式之工厂模式详解
Mar 03 Javascript
JavaScript动态加载样式表的方法
Mar 21 Javascript
jQuery调用WebMethod(PageMethod) NET2.0的方法
Apr 15 Javascript
jquery实现二级导航下拉菜单效果实例
May 14 jQuery
js根据后缀判断文件文件类型的代码
May 09 Javascript
Node.js API详解之 zlib模块用法分析
May 19 Javascript
jQuery实现移动端扭蛋机抽奖
Nov 08 jQuery
javascript iframe内的函数调用实现方法
Jul 19 #Javascript
9个javascript语法高亮插件 推荐
Jul 18 #Javascript
Google Map Api和GOOGLE Search Api整合实现代码
Jul 18 #Javascript
比较简单的异步加载JS文件的代码
Jul 18 #Javascript
用showModalDialog弹出页面后,提交表单总是弹出一个新窗口
Jul 18 #Javascript
DOM 基本方法
Jul 18 #Javascript
javascript 全角转换实现代码
Jul 17 #Javascript
You might like
php 文件上传后缀名与文件类型对照表(几乎涵盖所有文件)
2010/05/16 PHP
php学习之简单计算器实现代码
2011/06/09 PHP
php生成静态页面的简单示例
2014/04/17 PHP
php中数据库连接方式pdo和mysqli对比分析
2015/02/25 PHP
php生成圆角图片的方法
2015/04/07 PHP
用javascript实现分割提取页面所需内容
2007/05/09 Javascript
关于JS判断图片是否加载完成且获取图片宽度的方法
2013/04/09 Javascript
Jquery中val()表单取值赋值的实例代码
2013/08/15 Javascript
js 右侧浮动层效果实现代码(跟随滚动)
2015/11/22 Javascript
jQuery实现区域打印功能代码详解
2016/06/17 Javascript
JavaScript SHA-256加密算法详细代码
2016/10/06 Javascript
详解百度百科目录导航树小插件
2017/01/08 Javascript
jQuery实现checkbox即点即改批量删除及中间遇到的坑
2017/11/11 jQuery
angular1配合gulp和bower的使用教程
2018/01/19 Javascript
vue-cli 如何打包上线的方法示例
2018/05/08 Javascript
python画一个玫瑰和一个爱心
2020/08/18 Python
浅谈python3发送post请求参数为空的情况
2018/12/28 Python
Python图像的增强处理操作示例【基于ImageEnhance类】
2019/01/03 Python
利用PyCharm Profile分析异步爬虫效率详解
2019/05/08 Python
在python 中split()使用多符号分割的例子
2019/07/15 Python
matlab 计算灰度图像的一阶矩,二阶矩,三阶矩实例
2020/04/22 Python
解决Keras中Embedding层masking与Concatenate层不可调和的问题
2020/06/18 Python
Python如何读取、写入CSV数据
2020/07/28 Python
html5新特性与用法大全
2018/09/13 HTML / CSS
html5+svg学习指南之SVG基础知识
2014/12/17 HTML / CSS
南京迈特望C/C++面试题
2012/07/09 面试题
工厂门卫岗位职责
2013/11/25 职场文书
项目专员岗位职责
2013/12/04 职场文书
优秀教师事迹简介
2014/02/02 职场文书
小松树教学反思
2014/02/11 职场文书
正风肃纪查摆剖析材料
2014/10/10 职场文书
党员个人整改措施
2014/10/24 职场文书
2015年小学生自我评价范文
2015/03/03 职场文书
2016年第十四个公民道德宣传日活动总
2016/04/01 职场文书
vue打包时去掉所有的console.log
2022/04/10 Vue.js
Redis主从复制操作和配置详情
2022/09/23 Redis