- 浏览: 1326883 次
- 性别:
- 来自: 湖南澧縣
文章分类
最新评论
-
虾米小尹:
不行啊!2.2-0.25=1.9500000000000002 ...
JavaScript浮点数运算 —— 精度问题 -
heluping000000:
引用String a= "abc",首先在 ...
String,到底创建了多少个对象? -
mack:
谢谢分享matcher.appendReplacement(s ...
string.replaceAll()中的特殊字符($ \)与matcher.appendReplacement -
wzt3309:
完全理解,比网上其他资料都要详细
String,到底创建了多少个对象? -
u014771876:
Java中十六进制转换 Integer.toHexString()
-
zInherit
利用zInherit库(可以从http://www.nczonline.net/downloads 处下载),不必使用原型链,也可实现方法继承。
Inherit库给Object类添加了两个方法,inheritFrom()和instanceOf()。inheritFrom()方法负担重任,负责复制指定类的所有方法。下面一行代码用原型链使ClassB继承ClassA的方法:
ClassB.prototype = new ClassA();
可用下面代码替换上面的代码:
ClassB.prototype.inheritFrom(ClassA);
inheritFrom() 方法接受一个参数,即要复制的方法所属的类。注意,与原型链相对的是,这种方式并未真正创建要继承的类的实例(具体请参考zInherit源码),这样更安全,开发者也无需担心构造函数的参数。
instanceOf() 方法是instanceof运算符的替代品。因为这种方式根本不使用原型链,所以这行代码无效:
base3 instanceof Base1
但instanceOf()方法弥补了这项损失,与inheritFrom()一起使用,可以跟踪所有的超类:
base3.instanceOf(Base1);
zInherit多层继承具体示例代码如下:
function Base1(base1Name) { this.base1Name = base1Name; if (typeof Base1._initialized == "undefined") { Base1.prototype.getBase1 = function () { alert(this.base1Name); }; Base1._initialized = true; } } //Base2继承Base1 function Base2(base1Name, base2Name) { this.base2Name = base2Name; //使用call方式对属性继承 Base1.call(this, base1Name); if (typeof Base2._initialized == "undefined") { //使用zinherit方式对方法时行复制继承 Base2.prototype.inheritFrom(Base1); Base2.prototype.getBase2 = function () { alert(this.base2Name); }; Base2._initialized = true; } } //Base3继承Base2 function Base3(base1Name, base2Name, base3Name) { this.base3Name = base3Name; //使用call方式对属性继承 Base2.call(this, base1Name, base2Name); if (typeof Base3._initialized == "undefined") { //使用zinherit方式对方法时行复制继承 Base3.prototype.inheritFrom(Base2); Base3.prototype.getBase3 = function () { alert(this.base3Name); }; Base3._initialized = true; } } var base3 = new Base3("base1Name", "base2Name", "base3Name"); //Base3可以访问从父类Base2继承过来的方法 base3.getBase2();//base2Name //Base3可以访问从超类Base1继承过来的方法 base3.getBase1();//base1Name //当然更可以访问自己的方法 base3.getBase3();//base1Name //因为zinherit方式未采用原型链的方法,所以不支持instanceof alert(base3 instanceof Base1);//false //但可以用zinherit的instanceOf方法来避免该问题 alert(base3.instanceOf(Base1));//true alert(base3.instanceOf(Base2));//true alert(base3.instanceOf(Base3));//true
另外:原型链不能实现动态原型主旨,即把类的所有代码放置在它的构造函数中。zInherit库修正了这个问题,它允许在构造函数内部调用 inheritFrom()方法,使用inheritFrom()方法时,并未重写prototype对象,只是为其加入方法而已(从zInherit源码分析可知)。使用这种方法,即可避开原型链的限制,实现动态原型本意。所以zInherit支持动态原型,从上面的示例就可以看得出来。
zInherit的另一个好处就是除了支持多层继承、动态原型法,还支持多重继承,即一个类可以继承多个类,这些类是同一级别的。
zInherit多重继承示例如下,显示的结果与多层继承一样:
function Base1(base1Name) { this.base1Name = base1Name; if (typeof Base1._initialized == "undefined") { Base1.prototype.getBase1 = function () { alert(this.base1Name); }; Base1._initialized = true; } } function Base2(base2Name) { this.base2Name = base2Name; if (typeof Base2._initialized == "undefined") { Base2.prototype.getBase2 = function () { alert(this.base2Name); }; Base2._initialized = true; } } //多重继承:Base3继承Base1与Base2 function Base3(base1Name, base2Name, base3Name) { this.base3Name = base3Name; //使用call方式对属性继承 Base1.call(this, base1Name); Base2.call(this, base2Name); if (typeof Base3._initialized == "undefined") { //使用zinherit方式对方法时行复制继承 Base3.prototype.inheritFrom(Base1); Base3.prototype.inheritFrom(Base2); Base3.prototype.getBase3 = function () { alert(this.base3Name); }; Base3._initialized = true; } } var base3 = new Base3("base1Name", "base2Name", "base3Name"); //Base3可以访问从父类Base2继承过来的方法 base3.getBase2();//base2Name //Base3可以访问从超类Base1继承过来的方法 base3.getBase1();//base1Name //当然更可以访问自己的方法 base3.getBase3();//base3Name //因为zinherit方式未采用原型链的方法,所以不支持instanceof alert(base3 instanceof Base1);//false //但可以用zinherit的instanceOf方法来避免该问题 alert(base3.instanceOf(Base1));//true alert(base3.instanceOf(Base2));//true alert(base3.instanceOf(Base3));//true
zinherit.js源码分析
/** * Inherits properties and methods from the given class. * @scope public * @param fnClass The constructor function to inherit from. */ Object.prototype.inheritFrom = function (fnClass) { /** * Inherits all classes going up the inheritance chain recursively. * @param fnClass The class to inherit from. * @param arrClasses The array of classes to build up. * @scope private */ function inheritClasses(fnClass, arrClasses) { /* 把父类构造函数放入到子类构造函数的私有属性数组中,用数组实现多继承,即可以继承多个。 此数组里最后存放了所有父类及超类的构造函数,如果子类继承了多个类,则此数组会存储多个构造函数。 */ arrClasses.push(fnClass); //如果父类构造函数继承了其他类,则递归,这样可以实现多层继承 if (typeof fnClass.__superclasses__ == "object") { for (var i = 0; i < fnClass.__superclasses__.length; i++) { //fnClass.__superclasses__[i]为父类的构造函数,如果父类继承了多个类, //则fnClass.__superclasses__.length会大于1 inheritClasses(fnClass.__superclasses__[i], arrClasses); } } } //this为子类构造函数的原型 //this.constructor为子类构造函数 //this.constructor.__superclasses__为子类构造函数的私有属性数组 if (typeof this.constructor.__superclasses__ == "undefined") { //这里的数组用来实现instanceOf用的 this.constructor.__superclasses__ = new Array(); } //fnClass为父类构造函数 inheritClasses(fnClass, this.constructor.__superclasses__); //----上面的操作是为了instanceOf方法应用设计的,下面才是方法继承 //把父类原型里存储的方法复制到子类构造函数原型中(注:这里是方法地址的复制),而不是真真的方法复制 for (prop in fnClass.prototype) { if (typeof fnClass.prototype[prop] == "function") { //this为子类构造函数的原型实例,这里把父类原型实例中的属性(一般指方法属性,但不排除字 //段属性)一一复制到子类构造函数的原型实例中去。而不是采用原型链的方式:Base3.prototype=new Base2(); this[prop] = fnClass.prototype[prop]; } } }; /** * Determines if the given object is an instance of a given class. * This method is necessary because using {@link #inheritFrom} renders * the JavaScript <code>instanceof</code> operator useless. * @param fnClass The constructor function to test. * @return True if the object is an instance of the class, false if not. * @scope public */ Object.prototype.instanceOf = function (fnClass) { //如果是base3.instanceOf(Base3)时 if (this.constructor == fnClass) { return true; //如果是采用zinherit继承方式时,则this.constructor.__superclasses__为数组对象 } else { if (typeof this.constructor.__superclasses__ == "object") { //再进一步判断,如:调用base3.instanceOf(Base1)时 for (var i = 0; i < this.constructor.__superclasses__.length; i++) { if (this.constructor.__superclasses__[i] == fnClass) { return true; } } return false; } else { return false; } } };
-
xbObjects
由 Netscape 公司的 Bob Clary 于 2001 年 Netscape 6 ( Mozilla 0.6 )发布时编写而成。它支持从那时起的所有 Mozilla 版本及其他现代浏览器( IE 、 Opera 和 Safari )。可以从 http://archive.bclary.com/xbProjects-docs/xbObject/ 处下载。
支持继承,还支持方法的重载和调用超类方法的能力。
第一步,必须注册类,此时,需定义它是由哪个类继承而来:
这里,子类和超类名都以字符串形式传进来,而不是指向它们的构造函数的指针 。这个调用必须放在指定子类的构造 函数前 。
如果新的类未继承任何类,调用 registerClass() 时也可以只用第一个参数。
<script type="text/javascript"></script>
第二步 ,在构造函数内调用 defineClass() 方法 ,传给它类名及被 Clary 称为 原型函数 ( prototype function )的指针,该函数用于初始化对象的所有属性和方法 ,例如:
第三步,为该类创建 init() 方法 。该方法负责设置该类的所有属性 ,它必须接受与构造函数相同的参数。作为一种规定, init() 方法总是在 defineClass() 方法后调用 。例如:
init() 方法中调用的 parentMethod() 方法。 xbObjects 以这种方式允许类调用它的超类的方法 。 parentMethod() 方法接受任意多个参数,但第一个参数总是要调用的父类方法的名字(该参数必须是字符串,而不是函数指针),所有其他参数都被传给父类的方法。
在这个例子中,首先调用 init() 方法,这是 xbObjects 运行所必需的。即使 ClassA 未注册超类, xbObejcts 都会为它创建一个所有类的默认超类,即超类方法 init() 所属的类。
第四步 也是最后一步,在原型函数内添加其他类的方法 :
xbObjects多层继承示例如下:
//注册类 _classes.registerClass("Base1"); function Base1(base1Name) { //基于原型来初始化类的属性与方法 function prototypeFunction() { //init方法设置该类的所有属性,它必须接收与构造函数相同的参数签名 Base1.prototype.init = function (base1Name) { //... this.parentMethod("init"); this.base1Name = base1Name; }; //设置方法 Base1.prototype.getBase1 = function () { alert(this.base1Name); }; } //定义类,用来初始化对象所有属性与方法 _classes.defineClass("Base1", prototypeFunction); this.init(base1Name); } //Base2继承Base1 _classes.registerClass("Base2", "Base1"); function Base2(base1Name, base2Name) { function prototypeFunction() { //init方法接收与构造函数相同的参数签名 Base2.prototype.init = function (base1Name, base2Name) { //... this.parentMethod("init", base1Name); this.base2Name = base2Name; }; //设置方法 Base2.prototype.getBase2 = function () { alert(this.base2Name); }; } //定义类,用来初始化对象所有属性与方法 _classes.defineClass("Base2", prototypeFunction); this.init(base1Name, base2Name); } //Base3继承Base2 _classes.registerClass("Base3", "Base2"); function Base3(base1Name, base2Name, base3Name) { function prototypeFunction() { Base3.prototype.init = function (base1Name, base2Name, base3Name) { //... this.parentMethod("init", base1Name, base2Name); this.base3Name = base3Name; }; //设置方法 Base3.prototype.getBase3 = function () { alert(this.base3Name); }; } //定义类,用来初始化对象所有属性与方法 _classes.defineClass("Base3", prototypeFunction); this.init(base1Name, base2Name, base3Name); } var base3 = new Base3("base1Name", "base2Name", "base3Name"); //Base3可以访问从父类Base2继承过来的方法 base3.getBase2();//base2Name //Base3可以访问从超类Base1继承过来的方法 base3.getBase1();//base1Name //当然更可以访问自己的方法 base3.getBase3();//base3Name //因为xbObjects方式未采用原型链的方法,所以不支持instanceof alert(base3 instanceof Base1);//false //但可以用zinherit的instanceOf方法来避免该问题 alert(base3.isInstanceOf(Base1));//true alert(base3.isInstanceOf(Base2));//true alert(base3.isInstanceOf(Base3));//true
注:上面this.parentMethod("init"...)前最好不要加上中文注释,否则可能出问题。
附:zInherit、xbObjects
- zInherit1.0.zip (14.5 KB)
- 下载次数: 8
- xbObjects.rar (2.4 KB)
- 下载次数: 8
发表评论
-
HTML、JS、JSON特殊字符
2010-12-13 23:47 25821JS到HTML特殊字符转换 这几天做项目,发现从服务器端以J ... -
HTML — HTTP URL 中的特殊字符
2009-10-31 18:16 32481. + URL中的+号表示空格 ... -
HTML — CSS选择器
2009-10-25 21:11 2128一个样式规则由两部分组成:选择器和样式声明。选择器表明要为哪一 ... -
部分解决JsUnit无法在firefox3、safari 测试的问题
2009-10-25 07:03 1410在上一篇中出现了一个问题,就是用 jsunit2.2alpha ... -
JsUnit——eclipse插件(四)
2009-10-25 06:59 2407这节我们来看看如何通过JsUnit插件来运行前几节所测试过的测 ... -
10、JavaScript跨浏览器需注意的问题——ajax基础笔记
2009-10-21 22:19 1331向表中追加行 创建表格行时,我们要把创建的 tr 追加到 t ... -
JsUnit详解——Web服务方式(三)
2009-10-21 00:21 2405上两节提到过以Web方式来运行JsUnit,不过不是很详细,这 ... -
JsUnit详解——《ajax基础》笔记(二)
2009-10-20 22:38 2496使用标准/定制查询串 如此说来,测试运行工具是很强大的,但是 ... -
JsUnit详解——《ajax基础》笔记(一)
2009-10-20 19:57 2548JsUnit与JUnit对比 JsUnit也有setUp() ... -
使用Firefox的Web开发插件
2009-10-18 17:53 1445Firefox的Web开发插件为Firefox浏览器增加了大量 ... -
9、访问WEB服务(REST)——ajax基础笔记
2009-10-18 17:24 3983最其名的WEB服务实现是S ... -
8、读取响应头部——ajax基础笔记
2009-10-18 17:20 6722你有时可能需要从服务器获取一些内容,例如,可能想“ping”一 ... -
7、使用JSON向服务器发送数据——ajax基础笔记
2009-10-18 17:20 5147看过前面的例子后(使用XML向服务器发送复杂的数据结构),你可 ... -
6、请求参数作为XML发送——ajax基础笔记
2009-10-18 17:20 1732如果只是使用一个包含 名/值 对的简单查询串,这可能不够健壮, ... -
4、将使用W3C DOM动态生成页面——ajax基础笔记
2009-10-18 17:19 1375使用W3C DOM动态生成页面 dynamicContent ... -
3、将响应解析为XML——ajax基础笔记
2009-10-18 17:18 1025将响应解析为XML parseXML.xml清单: < ... -
2、使用innerHTML属性创建动态内容——ajax基础笔记
2009-10-18 17:17 1879使用innerHTML属性创建动态内容 如果结合作用HTML ... -
1、使用XMLHttpRequest对象——ajax基础笔记
2009-10-18 17:17 1987XMLHttpRequest最早是在 IE5 中以active ... -
30、JavaScript代码优化
2009-10-16 21:25 1534JavaScript代码的速度被分成两部分:下载时间和执行速度 ... -
JavaScript代码优化(二)
2009-10-16 01:32 1166◆字符串的使用 在IE6和IE7中因字符串级联导致的主要问题 ...
相关推荐
NULL 博文链接:https://dbajun.iteye.com/blog/242763
利用JavaScript实现图片标注——SearchMapIdentityTask
教你一天玩转JavaScript(四)——使用JavaScript实现定时弹出广告定时隐藏广告
教你一天玩转JavaScript(二)——完成对注册页面的数据的简单校验
JavaScript框架高级编程——应用Prototype、YUI、Ext JS、Dojo、MooTools JavaScript框架高级编程——应用Prototype、YUI、Ext JS、Dojo、MooTools
JavaScript代码生成器——Coffee Script.pdf
教你一天玩转JavaScript(三)——使用JavaScript完成图片轮播的效果
教你一天玩转JavaScript(七)——使用JavaScript完成复选框的全选和全不选的效果
JavaScript调用java方法——dwr步骤.docx
教你一天玩转JavaScript(五)——使用JavaScript完成注册页面表单提示及校验
教你一天玩转JavaScript(八)——使用JavaScript完成省市联动的效果
javascript 原生实现 省市区街——四级联动
zinherit JavaScript zinherit JavaScript zinherit JavaScript zinherit JavaScript zinherit JavaScript zinherit JavaScript zinherit JavaScript zinherit JavaScript
管理系统系列--全JavaScript语言Web项目——图书管理系统
教你一天玩转JavaScript(六)——使用JavaScript完成后台数据展示表格的隔行换色
JavaScript凌厉开发——Ext详解与实践 源码 源代码 part3 因为源代码比较大,压缩后76M左右 所以分为四个包上传
js javascript zInherit 对象 继承
Javascript定时器(二)——setTimeout与setInterval 在 http://www.cnblogs.com/strick/p/3983904.html 有说明