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.ajax)
Nov 19 Javascript
基于JQuery的asp.net树实现代码
Nov 30 Javascript
基于jQuery的合并表格中相同文本的相邻单元格的代码
Apr 06 Javascript
javascript学习笔记(二十) 获得和设置元素的特性(属性)
Jun 20 Javascript
当自定义数据属性为json格式字符串时jQuery的data api问题探讨
Feb 18 Javascript
JavaScript实现动画打开半透明提示层的方法
Apr 21 Javascript
Jquery左右滑动插件之实现超级炫酷动画效果附源码下载
Dec 02 Javascript
JavaScript继承模式粗探
Jan 12 Javascript
Javascript实现代码折叠功能
Aug 25 Javascript
AngularJS表格添加序号的方法
Mar 03 Javascript
vue实现歌手列表字母排序下拉滚动条侧栏排序实时更新
May 14 Javascript
VUE实现密码验证与提示功能
Oct 18 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
Yii框架中memcache用法实例
2014/12/03 PHP
CI框架表单验证实例详解
2016/11/21 PHP
基于Jquery的仿Windows Aero弹出窗(漂亮的关闭按钮)
2010/09/28 Javascript
悄悄用脚本检查你访问过哪些网站的代码
2010/12/04 Javascript
iframe子页面获取父页面元素的方法
2013/11/05 Javascript
javascript设置金额样式转换保留两位小数示例代码
2013/12/04 Javascript
jquery改变tr背景色的示例代码
2013/12/28 Javascript
javascript去除字符串左右两端的空格
2015/02/05 Javascript
jQuery中prepend()方法使用详解
2015/08/11 Javascript
javascript中alert()与console.log()的区别
2015/08/26 Javascript
Vue.js中extend选项和delimiters选项的比较
2017/07/17 Javascript
JS设计模式之观察者模式实现实时改变页面中金额数的方法
2018/02/05 Javascript
看看“疫苗查询”小程序有温度的代码
2018/07/31 Javascript
angularjs下ng-repeat点击元素改变样式的实现方法
2018/09/12 Javascript
vue 项目地址去掉 #的方法
2018/10/20 Javascript
微信小程序自定义导航教程(兼容各种手机)
2018/12/12 Javascript
浅析vue中的provide / inject 有什么用处
2019/11/10 Javascript
[02:29]DOTA2英雄基础教程 陈
2013/12/17 DOTA
[01:20]2018DOTA2亚洲邀请赛总决赛战队Mineski晋级之路
2018/04/07 DOTA
python基础教程之popen函数操作其它程序的输入和输出示例
2014/02/10 Python
python在linux中输出带颜色的文字的方法
2014/06/19 Python
python使用xlrd实现检索excel中某列含有指定字符串记录的方法
2015/05/09 Python
python模拟登录并且保持cookie的方法详解
2017/04/04 Python
Python 实现数据库(SQL)更新脚本的生成方法
2017/07/09 Python
使用python对文件中的单词进行提取的方法示例
2018/12/21 Python
简单了解python高阶函数map/reduce
2019/06/28 Python
Pytorch Tensor的索引与切片例子
2019/08/18 Python
利用python在大量数据文件下删除某一行的例子
2019/08/21 Python
django框架中ajax的使用及避开CSRF 验证的方式详解
2019/12/11 Python
tensorflow2.0的函数签名与图结构(推荐)
2020/04/28 Python
可视化pytorch 模型中不同BN层的running mean曲线实例
2020/06/24 Python
python如何求圆的面积
2020/07/01 Python
纯CSS3代码实现文字描边
2016/04/25 HTML / CSS
个人思想理论学习的自我鉴定
2013/11/30 职场文书
2015年房地产销售工作总结
2015/04/20 职场文书
小学三年级班主任工作经验交流材料
2015/11/02 职场文书