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 相关文章推荐
javascript 二分法(数组array)
Apr 24 Javascript
查询json的数据结构的8种方式简介
Mar 10 Javascript
多个$(document).ready()的执行顺序实例分析
Jul 26 Javascript
简介JavaScript中substring()方法的使用
Jun 06 Javascript
jquery中toggle函数交替使用问题
Jun 22 Javascript
javascript实现rgb颜色转换成16进制格式
Jul 10 Javascript
javascript的BOM汇总
Jul 16 Javascript
浅谈js继承的实现及公有、私有、静态方法的书写
Oct 28 Javascript
EsLint入门学习教程
Feb 17 Javascript
20行JS代码实现网页刮刮乐效果
Jun 23 Javascript
使用Vue中 v-for循环列表控制按钮隐藏显示功能
Apr 23 Javascript
vue项目实现分页效果
Mar 24 Vue.js
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仿盗链代码
2012/06/03 PHP
PHP中如何定义和使用常量
2013/02/28 PHP
解析PHP计算页面执行时间的实现代码
2013/06/18 PHP
php中文验证码实现示例分享
2014/01/12 PHP
php实现扫描二维码根据浏览器类型访问不同下载地址
2014/10/15 PHP
php读取文件内容的方法汇总
2015/01/24 PHP
如何使用Gitblog和Markdown建自己的博客
2015/07/31 PHP
PHP根据树的前序遍历和中序遍历构造树并输出后序遍历的方法
2017/11/10 PHP
禁止刷新,回退的JS
2006/11/25 Javascript
jquery select动态加载选择(兼容各种浏览器)
2013/02/01 Javascript
jquery实现智能感知连接外网搜索
2013/05/21 Javascript
javascript运算符——位运算符全面介绍
2016/07/14 Javascript
BootStrap 动态添加验证项和取消验证项的实现方法
2016/09/28 Javascript
关于Jquery中的事件绑定总结
2016/10/26 Javascript
Javascript数组中push方法用法分析
2016/10/31 Javascript
BootStrap中
2016/12/10 Javascript
一个例子轻松学会Vue.js
2017/01/02 Javascript
关于Webpack dev server热加载失败的解决方法
2018/02/22 Javascript
详解vue axios用post提交的数据格式
2018/08/07 Javascript
Vue在chrome44偶现点击子元素事件无法冒泡的解决方法
2019/12/15 Javascript
windows系统中python使用rar命令压缩多个文件夹示例
2014/05/06 Python
Python批量合并有合并单元格的Excel文件详解
2018/04/05 Python
Tensorflow中的placeholder和feed_dict的使用
2018/07/09 Python
浅谈python str.format与制表符\t关于中文对齐的细节问题
2019/01/14 Python
详解Python数据可视化编程 - 词云生成并保存(jieba+WordCloud)
2019/03/26 Python
css3中背景尺寸background-size详解
2014/09/02 HTML / CSS
html5 canvas合成海报所遇问题及解决方案总结
2017/08/03 HTML / CSS
英国著名的小众美容品牌网站:Alyaka
2017/08/08 全球购物
山海经纬软件测试笔试题和面试题
2013/04/02 面试题
4s店总经理岗位职责
2013/12/31 职场文书
人事经理岗位职责
2014/04/28 职场文书
银行金融服务方案
2014/06/11 职场文书
同意报考证明
2015/06/17 职场文书
幼儿园中班教育随笔
2015/08/14 职场文书
2019个人工作态度自我评价
2019/04/24 职场文书
CSS3 Tab动画实例之背景切换动态效果
2021/08/23 HTML / CSS