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 相关文章推荐
JS解析XML实例分析
Jan 30 Javascript
解析Node.js基于模块和包的代码部署方式
Feb 16 Javascript
jquery制做精致的倒计时特效
Jun 13 Javascript
浅谈jQuery添加的HTML,JS失效的问题
Oct 05 Javascript
canvas学习之API整理笔记(二)
Dec 29 Javascript
jQuery实现动态生成表格并为行绑定单击变色动作的方法
Apr 17 jQuery
vue+swiper实现侧滑菜单效果
Dec 28 Javascript
详解VUE2.X过滤器的使用方法
Jan 11 Javascript
vue 标签属性数据绑定和拼接的实现方法
May 17 Javascript
详解Angular6 热加载配置方案
Aug 18 Javascript
H5+C3+JS实现双人对战五子棋游戏(UI篇)
May 28 Javascript
深入解析微信小程序开发中遇到的几个小问题
Jul 11 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
zend api扩展的php对象的autoload工具
2011/04/18 PHP
php header Content-Type类型小结
2011/07/03 PHP
20个PHP常用类库小结
2011/09/11 PHP
zf框架db类的分页示例分享
2014/03/14 PHP
javascript 火狐(firefox)不显示本地图片问题解决
2008/07/05 Javascript
js 代码优化点滴记录
2012/02/19 Javascript
JQUERY 实现窗口滚动搜索框停靠效果(类似滚动停靠)
2013/03/27 Javascript
jQuery图片的展开和收缩实现代码
2013/04/16 Javascript
jQuery中RadioButtonList的功能及用法实例介绍
2013/08/23 Javascript
将list转换为json失败的原因
2013/12/17 Javascript
JavaScript通过字典进行字符串翻译转换的方法
2015/03/19 Javascript
js图片切换具体实现代码
2016/10/13 Javascript
手动下载Chrome并解决puppeteer无法使用问题
2018/11/12 Javascript
vue 集成jTopo 处理方法
2019/08/07 Javascript
webpack.DefinePlugin与cross-env区别详解
2020/02/23 Javascript
使用JavaScript实现网页秒表功能(含开始、暂停、继续、重置功能)
2020/06/05 Javascript
vue仿携程轮播图效果(滑动轮播,下方高度自适应)
2021/02/11 Vue.js
使用Python操作Elasticsearch数据索引的教程
2015/04/08 Python
Django学习笔记之Class-Based-View
2017/02/15 Python
Python反射的用法实例分析
2018/02/11 Python
Win7 64位下python3.6.5安装配置图文教程
2020/10/27 Python
Python多进程原理与用法分析
2018/08/21 Python
Python-ElasticSearch搜索查询的讲解
2019/02/25 Python
Python绘制热力图示例
2019/09/27 Python
在Keras中实现保存和加载权重及模型结构
2020/06/15 Python
python从ftp获取文件并下载到本地
2020/12/05 Python
详解使用python爬取抖音app视频(appium可以操控手机)
2021/01/26 Python
html5定位并在百度地图上显示的示例
2014/04/27 HTML / CSS
奥地利汽车配件店:Pkwteile.at
2017/03/10 全球购物
Derek Rose官网:英国高档睡衣、家居服和内衣品牌
2020/01/18 全球购物
房地产出纳岗位职责
2013/12/01 职场文书
《黄河颂》教学反思
2014/02/07 职场文书
国际贸易毕业生自荐书
2014/06/22 职场文书
先进个人总结范文
2015/02/15 职场文书
毛主席纪念堂观后感
2015/06/17 职场文书
有关浪费资源的建议书
2015/09/14 职场文书