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 相关文章推荐
jQuery使用手册之二 DOM操作
Mar 24 Javascript
在IE 浏览器中使用 jquery的fadeIn() 效果 英文字符字体加粗
Jun 02 Javascript
基于JQuery 选择器使用说明介绍
Apr 18 Javascript
js的toLowerCase方法用法实例
Jan 27 Javascript
jQuery简单实现上下,左右滑动的方法
Jun 01 Javascript
详解React开发中使用require.ensure()按需加载ES6组件
May 12 Javascript
使用Vue开发动态刷新Echarts组件的教程详解
Mar 22 Javascript
vue  自定义组件实现通讯录功能
Sep 30 Javascript
Iview Table组件中各种组件扩展的使用
Oct 20 Javascript
three.js搭建室内场景教程
Dec 30 Javascript
Node 代理访问的实现
Sep 19 Javascript
vue 设置 input 为不可以编辑的实现方法
Sep 19 Javascript
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(1)
2006/10/09 PHP
114啦源码(114la)不能生成地方房产和地方报刊问题4级页面0字节的解决方法
2012/01/12 PHP
php实现的九九乘法口诀表简洁版
2014/07/28 PHP
简单分析ucenter 会员同步登录通信原理
2014/08/25 PHP
php递归法读取目录及文件的方法
2015/01/30 PHP
yii2中添加验证码的实现方法
2016/01/09 PHP
Thinkphp3.2简单解决多文件上传只上传一张的问题
2017/09/26 PHP
前端轻量级MVC框架CanJS详解
2014/09/26 Javascript
jQuery中用dom操作替代正则表达式
2014/12/29 Javascript
js实现仿网易点击弹出提示同时背景变暗效果
2015/08/13 Javascript
javascript跑马灯抽奖实例讲解
2020/04/17 Javascript
js实现兼容PC端和移动端滑块拖动选择数字效果
2017/02/16 Javascript
AngularJS中$http的交互问题
2017/03/29 Javascript
js使用formData实现批量上传
2020/03/27 Javascript
微信小程序实现上传照片代码实例解析
2020/08/04 Javascript
Python脚本实现网卡流量监控
2015/02/14 Python
Python 网页解析HTMLParse的实例详解
2017/08/10 Python
python实现遍历文件夹修改文件后缀
2018/08/28 Python
python 自定义对象的打印方法
2019/01/12 Python
python安装pil库方法及代码
2019/06/25 Python
python中调试或排错的五种方法示例
2019/09/12 Python
在python中利用try..except来代替if..else的用法
2019/12/19 Python
Django认证系统user对象实现过程解析
2020/03/02 Python
Python切割图片成九宫格的示例代码
2020/03/10 Python
快速解决Django关闭Debug模式无法加载media图片与static静态文件
2020/04/07 Python
Python+Kepler.gl实现时间轮播地图过程解析
2020/07/20 Python
python中altair可视化库实例用法
2021/01/26 Python
浅谈html5之sse服务器发送事件EventSource介绍
2017/08/28 HTML / CSS
英国知名美妆护肤在线商城:Zest Beauty
2018/04/24 全球购物
财务管理专业毕业生求职信范文
2013/09/21 职场文书
室内设计实习自我鉴定
2013/09/25 职场文书
大学生护理专业自荐信
2013/10/03 职场文书
人力资源经理的岗位职责范本
2014/02/28 职场文书
单位个人查摆问题及整改措施
2014/10/28 职场文书
介绍信的格式
2015/01/30 职场文书
投标售后服务承诺书
2015/04/29 职场文书