JS中,子类调用超类函数
概述
// 定义类A function A(a) { this.a = a; } // 为类A定义show方法 A.prototype.show = function() { alert("A: " + this.a); };
定义类B并从A继承
// 定义类B function B(a, b) { // 调用A的构造函数 A.apply(this, arguments); this.b = b; } // 链接A的原型 B.prototype = new A();
var b = new B(100, 200); b.show();此时,会执行定义在A中的show方法(显示A.a的值),表示类B已经从类A中继承了show方法
// 覆盖show方法 B.prototype.show = function() { A.prototype.show.apply(this, arguments); alert("B: " + this.b); }; // 执行覆盖后的方法 b.show();在B的prototype中重新定义show方法,即可以认为B类覆盖了A类的show方法。注意 A.prototype.show.apply(this, arguments) 这一句,实际上是利用了JS的原型特性,在B类对象中(以B类对象)执行了一次A类的show方法。
更进一步
// 定义根命名空间 ALV = {}; // 定义注册命名空间的方法 ALV.namespace = function(ns) { var root = window; var parts = ns.split("."); for (var i = 0; i < parts.length; i++) { var p = parts[i]; if (!root[p]) { root[p] = {}; } root = root[p]; } };
合并对象的apply方法
// 合并对象成员 ALV.apply = function(obja, objb, def) { if (def) { ALV.apply(obja, def); } if (obja && objb && typeof objb === 'object') { for (var o in objb) { obja[o] = objb[o]; } } };
// 原型定义 ALV.define = function(clazz, config) { var parts = clazz.split("."); var root = window; for (var i = 0; i < parts.length - 1; i++) { root = root[parts[i]]; } var cn = parts[parts.length - 1]; if (!root[cn]) { root[cn] = function() {}; } clazz = root[cn]; // 将proto对象的成员赋值给类的原型 ALV.apply(clazz.prototype, config); return clazz; };
// 定义继承的方法 ALV.extend = function(base, child, proto) { // 将超类原型赋值给类的原型 var c = ALV.define(child); if (base && typeof base === "function") { c.prototype = new base(); } if (proto && typeof proto == "object") { ALV.apply(c.prototype, proto); } // 调用超类方法 c.prototype.callParent = function(args) { var m; for (var o in this) { if (this[o] === this.callParent.caller) { m = o; } } var method = base.prototype[m]; if (method && typeof method === "function") { method.apply(this, args); } }; };上述代码中,子类的 prototype 链接到了超类对象上,完成了 prototype 的继承,而 callParent 方法中,通过对当前类调用方法的查找,找到方法名(m变量),再在超类的 prototype 中找到同名方法,利用超类方法的 apply 操作,在子类对象上完成对超类方法的调用。
测试代码
// 定义命名空间 ALV.namespace("Alvin.test"); // 定义超类 ALV.define("Alvin.test.A", { a: 100, show: function() { alert("A: " + this.a); } }); // 定义子类 ALV.extend(Alvin.test.A, "Alvin.test.B", { a: 100, b: 200, show: function() { this.callParent(arguments); alert("B: " + this.b); } }); // 实例化B类对象 var b = new Alvin.test.B(); b.show();
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。