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随机排序(随即出牌)
Sep 17 Javascript
jquery判断字符输入个数(数字英文长度记为1,中文记为2,超过长度自动截取)
Oct 15 Javascript
JS中不为人知的五种声明Number的方式简要概述
Feb 22 Javascript
鼠标放在图片上显示大图的JS代码
Mar 26 Javascript
jquery+php实现搜索框自动提示
Nov 28 Javascript
浅谈javascript中的instanceof和typeof
Feb 27 Javascript
Angualrjs和bootstrap相结合实现数据表格table
Mar 30 Javascript
Web技术实现移动监测的介绍
Sep 18 Javascript
使用Electron构建React+Webpack桌面应用的方法
Dec 15 Javascript
JS中实现一个下载进度条及播放进度条的代码
Jun 10 Javascript
localstorage实现带过期时间的缓存功能
Jun 28 Javascript
javascript canvas实现简易时钟例子
Sep 05 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
异世界新番又来了,同样是从零开始,男主的年龄降到5岁
2020/04/09 日漫
thinkPHP导出csv文件及用表格输出excel的方法
2015/12/30 PHP
jQuery随便控制任意div隐藏的方法
2013/06/28 Javascript
jquery实现省市select下拉框的替换(示例代码)
2014/02/22 Javascript
JQuery获取与设置HTML元素的内容或文本的实现代码
2014/06/20 Javascript
Js为表单动态添加节点内容的方法
2015/02/10 Javascript
Jsonp post 跨域方案
2015/07/06 Javascript
基于jquery实现在线选座订座之影院篇
2015/08/24 Javascript
ionic中列表项增加和删除的实现方法
2017/01/22 Javascript
nodejs中实现修改用户路由功能
2019/05/24 NodeJs
vue vant Area组件使用详解
2019/12/09 Javascript
详细分析vue表单数据的绑定
2020/07/20 Javascript
[04:16]完美世界DOTA2联赛PWL S2 集锦第一期
2020/11/23 DOTA
Python中的jquery PyQuery库使用小结
2014/05/13 Python
python中urllib.unquote乱码的原因与解决方法
2017/04/24 Python
利用Python读取文件的四种不同方法比对
2017/05/18 Python
基于Django contrib Comments 评论模块(详解)
2017/12/08 Python
django admin组件使用方法详解
2019/07/19 Python
简单了解django缓存方式及配置
2019/07/19 Python
Python for循环与getitem的关系详解
2020/01/02 Python
Python 列表的清空方式
2020/01/13 Python
python实现百度OCR图片识别过程解析
2020/01/17 Python
python 回溯法模板详解
2020/02/26 Python
关于Kotlin中SAM转换的那些事
2020/09/15 Python
Marmot土拨鼠官网:美国专业户外运动品牌
2018/01/11 全球购物
学生个人求职自荐信格式
2013/09/23 职场文书
小学教师师德反思
2014/02/03 职场文书
幼儿园毕业典礼主持词
2014/03/21 职场文书
建筑公司员工自我鉴定
2014/04/08 职场文书
交通事故协议书范文
2014/10/23 职场文书
观看焦裕禄观后感
2015/06/09 职场文书
2016年寒假见闻
2015/10/10 职场文书
浅谈node.js中间件有哪些类型
2021/04/29 Javascript
在Django中使用MQTT的方法
2021/05/10 Python
python b站视频下载的五种版本
2021/05/27 Python
K8s部署发布Golang应用程序的实现方法
2021/07/16 Golang