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的性能
Feb 06 Javascript
上传图片js判断图片尺寸和格式兼容IE
Sep 01 Javascript
jquery+CSS3模拟Path2.0动画菜单效果代码
Aug 31 Javascript
Winform客户端向web地址传参接收参数的方法
May 17 Javascript
js控件Kindeditor实现图片自动上传功能
Jul 20 Javascript
js中scrollTop()方法和scroll()方法用法示例
Oct 03 Javascript
js 模仿锚点定位的实现方法
Nov 19 Javascript
解决AjaxFileupload 上传时会出现连接重置的问题
Jul 07 Javascript
利用Vue实现一个markdown编辑器实例代码
May 19 Javascript
JavaScript使用百度ECharts插件绘制饼图操作示例
Nov 26 Javascript
vue-cli3 引入 font-awesome的操作
Aug 11 Javascript
jquery实现鼠标悬浮弹出气泡提示框
Dec 23 jQuery
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入门小知识
2008/03/24 PHP
PHP中PDO的错误处理
2011/09/04 PHP
让ThinkPHP支持大小写url地址访问的方法
2014/10/31 PHP
主流PHP框架的优缺点对比分析
2014/12/25 PHP
Alliance vs Liquid BO3 第一场2.13
2021/03/10 DOTA
学习jquery之一
2007/04/27 Javascript
ExtJS 学习专题(一) 如何应用ExtJS(附实例)
2010/03/11 Javascript
js关闭父窗口时关闭子窗口
2013/04/01 Javascript
JavaScript在浏览器标题栏上显示当前日期和时间的方法
2015/03/19 Javascript
聊一聊JS中this的指向问题
2016/06/17 Javascript
详解express与koa中间件模式对比
2017/08/07 Javascript
JS简单实现点击跳转登陆邮箱功能的方法
2017/10/31 Javascript
解决IE11 vue +webpack 项目中数据更新后页面没有刷新的问题
2018/09/25 Javascript
17道题让你彻底理解JS中的类型转换
2019/08/08 Javascript
[02:46]2014DOTA2国际邀请赛 选手为你解读比赛MVP充满梦想
2014/07/09 DOTA
[05:16]《大圣!大圣》——DOTA2新英雄齐天大圣配音李世宏老师专访
2016/12/13 DOTA
[00:16]热血竞技场
2019/03/06 DOTA
python使用os模块的os.walk遍历文件夹示例
2014/01/27 Python
windows系统下Python环境的搭建(Aptana Studio)
2017/03/06 Python
完美解决Python 2.7不能正常使用pip install的问题
2018/06/12 Python
centos 安装Python3 及对应的pip教程详解
2019/06/28 Python
python 实现屏幕录制示例
2019/12/23 Python
html5组织内容_动力节点Java学院整理
2017/07/10 HTML / CSS
Chemist Warehouse中文网:澳洲连锁大药房
2021/02/05 全球购物
网络体系结构及协议的定义
2014/03/13 面试题
中学教师培训制度
2014/01/31 职场文书
民族团结先进个人材料
2014/02/05 职场文书
军训口号
2014/06/13 职场文书
信仰纪录片观后感
2015/06/08 职场文书
廉洁自律准则学习心得体会
2016/01/13 职场文书
你为什么是穷人?可能是这5个缺点造成
2019/07/11 职场文书
传单、海报早OUT了,另类传单营销方案送给你!
2019/07/15 职场文书
numpy数据类型dtype转换实现
2021/04/24 Python
MySQL中varchar和char类型的区别
2021/11/17 MySQL
Oracle用户管理及赋权
2022/04/24 Oracle
Python测试框架pytest核心库pluggy详解
2022/08/05 Golang