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 easyui window 窗口关闭时的提示
Jun 22 Javascript
js判断设备是否为PC并调整图片大小
Feb 12 Javascript
node.js操作mysql(增删改查)
Jul 24 Javascript
JavaScript直播评论发弹幕切图功能点集合效果代码
Jun 26 Javascript
JavaScript DOM 对象深入了解
Jul 20 Javascript
JS图片压缩(pc端和移动端都适用)
Jan 12 Javascript
js仿淘宝评价评分功能
Feb 28 Javascript
鼠标经过出现气泡框的简单实例
Mar 17 Javascript
利用jsonp与代理服务器方案解决跨域问题
Sep 14 Javascript
layui表格数据重载
Jul 27 Javascript
ES6中let、const的区别及变量的解构赋值操作方法实例分析
Oct 15 Javascript
通过vue.extend实现消息提示弹框的方法记录
Jan 07 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
ASP和PHP都是可以删除自身的
2007/04/09 PHP
php实现的简单压缩英文字符串的代码
2008/04/24 PHP
PHP中文乱码解决方案
2015/03/05 PHP
PHP获取客户端及服务器端IP的封装类
2016/07/21 PHP
解决Laravel5.x的php artisan migrate数据库迁移创建操作报错SQLSTATE[42000]
2020/04/06 PHP
Jquery 一次处理多个ajax请求的代码
2011/09/02 Javascript
Js sort排序使用方法
2011/10/17 Javascript
js获取IFRAME当前的URL的方法
2013/11/13 Javascript
jQuery鼠标事件汇总
2015/08/30 Javascript
Bootstrap Fileinput文件上传组件用法详解
2016/05/10 Javascript
jQuery焦点图轮播插件KinSlideshow用法分析
2016/06/08 Javascript
原生js封装的一些jquery方法(详解)
2016/09/20 Javascript
web 屏蔽BackSpace键实例代码
2016/12/24 Javascript
JS路由跳转的简单实现代码
2017/09/21 Javascript
基于Vue实现平滑过渡的拖拽排序功能
2019/06/12 Javascript
解决vuex刷新状态初始化的方法实现
2019/08/15 Javascript
微信小程序swiper使用网络图片不显示问题解决
2019/12/13 Javascript
vue iview实现动态新增和删除
2020/06/17 Javascript
Python爬虫代理IP池实现方法
2017/01/05 Python
Python过滤txt文件内重复内容的方法
2018/10/21 Python
python实现QQ空间自动点赞功能
2019/04/09 Python
python实现简单聊天室功能 可以私聊
2019/07/12 Python
vscode配置anaconda3的方法步骤
2020/08/08 Python
澳大利亚牛仔裤商店:Just Jeans
2016/10/13 全球购物
德国网上超市:myTime.de
2019/08/26 全球购物
存储过程和函数的区别
2013/05/28 面试题
JPA的特点
2014/10/25 面试题
群众路线党课主持词
2014/04/01 职场文书
开学寄语大全
2014/04/08 职场文书
好听的队名和口号
2014/06/09 职场文书
中国梦演讲稿3分钟
2014/08/19 职场文书
预备党员2014年第四季度思想汇报范文
2014/10/25 职场文书
商业门面租房协议书
2014/11/25 职场文书
三下乡活动心得体会
2016/01/23 职场文书
SQL语句中JOIN的用法场景分析
2021/07/25 SQL Server
游戏《东方异文石:爱亚利亚黎明》正式版发布
2022/04/03 其他游戏