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 mapreduce工作原理简析
Nov 25 Javascript
8个实用的jQuery技巧
Mar 04 Javascript
jquery淡化版banner异步图片文字效果切换图片特效
Apr 08 Javascript
js调试系列 源码定位与调试[基础篇]
Jun 18 Javascript
HTML5使用DeviceOrientation实现摇一摇功能
Jun 05 Javascript
JavaScript学习笔记(三):JavaScript也有入口Main函数
Sep 12 Javascript
angular route中使用resolve在uglify压缩后问题解决
Sep 21 Javascript
详解用node-images 打造简易图片服务器
May 08 Javascript
详解angularjs利用ui-route异步加载组件
May 21 Javascript
深入理解 webpack 文件打包机制(小结)
Jan 08 Javascript
解决bootstrap模态框数据缓存的问题方法
Aug 10 Javascript
Vue+Element ui 根据后台返回数据设置动态表头操作
Sep 21 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生成静态页面教程
2012/01/10 PHP
PHP生成验证码时“图像因其本身有错无法显示”的解决方法
2013/08/07 PHP
PHP的PSR规范中文版
2013/09/28 PHP
php的SimpleXML方法读写XML接口文件实例解析
2014/06/16 PHP
thinkphp5 框架结合plupload实现图片批量上传功能示例
2020/04/04 PHP
当前页禁止复制粘贴截屏代码小集
2013/07/24 Javascript
js的.innerHTML = &quot;&quot;IE9下显示有错误的解决方法
2013/09/16 Javascript
node.js实现BigPipe详解
2014/12/05 Javascript
jQuery实现给页面换肤的方法
2015/05/30 Javascript
Js的Array数组对象详解
2016/02/22 Javascript
jquery输入数字随机抽奖特效的简单实现代码
2016/06/10 Javascript
JavaScript浮点数及运算精度调整详解
2016/10/21 Javascript
vue中使用vue-router切换页面时滚动条自动滚动到顶部的方法
2017/11/28 Javascript
Vue项目分环境打包的实现步骤
2018/04/02 Javascript
react实现点击选中的li高亮的示例代码
2018/05/24 Javascript
在create-react-app中使用css modules的示例代码
2018/07/31 Javascript
vue实现行列转换的一种方法
2019/08/06 Javascript
Vue 中 a标签上href无法跳转的解决方式
2019/11/12 Javascript
vue实现导航菜单和编辑文本的示例代码
2020/07/04 Javascript
js+canvas实现五子棋小游戏
2020/08/02 Javascript
python搭建简易服务器分析与实现
2012/12/15 Python
Python使用ntplib库同步校准当地时间的方法
2016/07/02 Python
Python简单实现阿拉伯数字和罗马数字的互相转换功能示例
2018/04/17 Python
python 读取目录下csv文件并绘制曲线v111的方法
2018/07/06 Python
详细介绍Python进度条tqdm的使用
2019/07/31 Python
Python使用matplotlib 模块scatter方法画散点图示例
2019/09/27 Python
Python实现线性插值和三次样条插值的示例代码
2019/11/13 Python
Python爬取YY评级分数并保存数据实现过程解析
2020/06/01 Python
Python3爬虫中pyspider的安装步骤
2020/07/29 Python
python实现sm2和sm4国密(国家商用密码)算法的示例
2020/09/26 Python
python爬虫快速响应服务器的做法
2020/11/24 Python
台湾东南旅游社网站:东南旅游
2019/02/11 全球购物
大学生军训广播稿
2014/01/24 职场文书
预备党员政审材料
2014/02/04 职场文书
国际贸易求职信
2014/07/05 职场文书
《认识钟表》教学反思
2016/02/16 职场文书