js继承类库,根据henry_feng改造的轮子
原文地址:http://blog.csdn.net/henry_feng
集成类实现以下功能:
- 类注册register
- 类创建及初始化createClass
- 子类中显示初始化父类:base(..)
- 私有方法,不支持继承private
- 多继承
- 继承多态virtual
- 子类中调用基类方法base(["basename"]).
- 函数覆盖override
- 抽象类abstract
- 静态构造createInstance
- instanceOf测试
- 方法支持in测试
先贴例子:
基类:
1 define(["oo", "exports"], function (oo, exports) { 2 3 var s = function () { 4 var privateval = "base"; 5 var a = Array.prototype.slice.call(arguments); 6 7 this.getInitParamater = function () {//私用方法,不会被继承 8 return a; 9 } 10 11 this.baseGet = function () {//私用方法,不会被继承 12 return privateval; 13 } 14 } 15 s.prototype.getName = function () {//可以被继承的方法 16 return this.baseGet(); 17 } 18 19 s.prototype.virtualGet = function () { 20 return this.getName();//多态 21 } 22 23 s.prototype.trueVirtual = function () { 24 throw new TypeError("trueVirtual");//模拟abstract 25 } 26 27 oo.register("xxxxxxx.OOTest.OoBase", s);//注册类 28 29 });
子类:
1 define(["oo", "require", "exports"], function (oo, require, exports) { 2 3 var s = function (a, b) { 4 var _super = this.base("xxxxxx.OOTest.OoBase", a, b);//开头初始化基类并得到操作对象 5 6 var privateval = "sub";//私有变量 7 8 this.subGet= function () { 9 return privateval; 10 } 11 12 this.baseGetName = function () { 13 return _super.getName();//内部调用基类方法 14 } 15 } 16 17 s.prototype.getName = function () {//覆盖 18 return this.subGet(); 19 } 20 21 s.parent = "xxxxxxxx.OOTest.OoBase"; 22 23 oo.register("xxxxxxxx.OOTest.OoSub", s); 24 25 return s; 26 });
库:
1 define(function (require, exports, module) { 2 var oofactory = { 3 _: {}, 4 DEBUG: true 5 }; 6 7 var pkg = null; 8 9 var isRoot = function (root) { 10 return root && (isWindow(root) || isObject(root)); 11 } 12 13 var isFunction = function (fun) { 14 return typeof (fun) === "function"; 15 } 16 17 var isObject = function (obj) { 18 var type = typeof obj; 19 return type === 'function' || type === 'object' && !!obj; 20 } 21 22 var isWindow = function (obj) { 23 /* jshint eqeqeq: false */ 24 return obj != null && obj == obj.window; 25 } 26 27 var isArray = function (obj) { 28 return toString.call(obj) === '[object Array]' 29 } 30 31 var contains = function (arr, str) { 32 if (!arr || !isArray(arr)) return -1; 33 for (var i = 0; i < arr.length; i++) { 34 if (arr[i] === str) { 35 return i; 36 } 37 } 38 return -1; 39 } 40 41 //function inhertPrototype(sub, _super) { 42 // var prototype = object(_super.prototype); 43 // prototype.constructor = sub; 44 // sub.prototype = prototype; 45 //} 46 47 //function isPrototypeProperty(obj, name) { 48 // return !(name in obj) && !obj.hasOwnProperty(name); 49 //} 50 51 //function isProperty(obj, name) { 52 // return name in obj; 53 //} 54 55 //var inject = function (obj, _super) { 56 // //只往当前this上绑定,通过context实现递归复制 57 // for (var x in _super) { 58 // obj[x] = obj[x] || ( 59 // isFunction(_super[x]) ? 60 // cloneFunction(_super[x]) : 61 // _super[x]); 62 // } 63 // return _super; 64 //} 65 var cloneFunction = function (funres) { 66 var temp = function temporary() { return funres.apply(this, arguments); }; 67 for (key in funres) { 68 temp[key] = funres[key]; 69 } 70 return temp; 71 } 72 73 var injectprototype = function (obj, clazz) { 74 var prototype = clazz.prototype; 75 for (var p in prototype) { 76 if (p == "constructor" || p == "__proto__") continue; 77 obj[p] = isFunction(prototype[p]) ? cloneFunction(prototype[p]) : prototype[p]; 78 } 79 } 80 81 var JOObject = function (className) { 82 this._ = []; 83 this.className = className || "JOObject"; 84 } 85 86 JOObject.className = "JOObject"; 87 88 JOObject.prototype.getClassName = function () { 89 return this.className; 90 } 91 92 JOObject.prototype.base = function (baseName) { 93 var index = -1; 94 if (!baseName) { 95 if (this._.length) return this._[1]; 96 } 97 else if ((index = contains(this._, baseName)) > -1) { 98 return this._[index + 1]; 99 } 100 //继承 101 var parent = oofactory.classForName(baseName); 102 //这个是复制构造函数中的this定义的方法,不复制相当于选择继承的方式,全复制则打开即可 103 //parent.apply(this, Array.prototype.slice(arguments, 1)); 104 //复制prototype定义的方法 105 injectprototype(this, parent); 106 //父类 107 var _super = oofactory.createClass.apply(null, Array.prototype.slice.call(arguments)); 108 //搭建关系 109 this._.push(baseName); 110 this._.push(_super); 111 return _super; 112 } 113 114 JOObject.prototype.instanceOf = function (baseName) { 115 if (baseName == this.getClassName() || baseName == JOObject.className) { 116 return true; 117 } 118 index = contains(this._, baseName); 119 if (index > -1) return true; 120 for (var i = 1; i < this._.length; i += 2) { 121 var basei = this._[i]; 122 if (basei.instanceOf(baseName)) { 123 return true; 124 } 125 } 126 return false; 127 } 128 129 var Package = function () { 130 131 this.createClassPkg = function (className) { 132 this.createPackage(this.getParent(className)); 133 }; 134 135 this.classForName = function (className) { 136 var ns = className.split("."); 137 var np = oofactory._; 138 for (var j = 0; j < ns.length; j++) { 139 var name = ns[j]; 140 if (np[name] === undefined) { 141 return np[name]; 142 } 143 np = np[name]; 144 } 145 return np; 146 }; 147 148 this.createPackage = function (pkgName) { 149 var ns = pkgName.split("."); 150 var np = oofactory._; 151 for (var j = 0; j < ns.length; j++) { 152 var name = ns[j]; 153 if (np[name] === undefined) { 154 console.log("create package: " + name); 155 } 156 np[name] = np[name] || {}; 157 np = np[name]; 158 } 159 return np; 160 }; 161 162 this.getPackage = function (className) { 163 var pkgName = this.getParent(className); 164 return this.createPackage(pkgName); 165 }; 166 167 this.getParent = function (className) { 168 var idx = className.lastIndexOf("."); 169 if (idx > 0) { 170 return className.substr(0, idx); 171 } else { 172 return ""; 173 } 174 }; 175 176 this.getSimpleName = function (className) { 177 var idx = className.lastIndexOf("."); 178 if (idx > 0) { 179 return className.substr(idx + 1); 180 } else { 181 return className; 182 } 183 }; 184 } 185 186 oofactory.register = function (className, clazz, parents) { 187 if (clazz['createInstance'] == null) {//静态方法 188 clazz['createInstance'] = function () { 189 return oofactory.createClass.apply(null, [className].concat(Array.prototype.slice.call(arguments))); 190 }; 191 } 192 193 if (clazz['className'] == null) {//静态方法 194 clazz['className'] = className; 195 } 196 197 //默认注册到window上 198 if (isRoot(oofactory._)) { 199 pkg = pkg || new Package(oofactory._); 200 var pkgName = pkg.getPackage(className); 201 pkgName[pkg.getSimpleName(className)] = clazz; 202 } 203 }; 204 205 oofactory.createClass = function () { 206 var args = Array.prototype.slice.call(arguments); 207 var className = args[0]; 208 var clazz = oofactory.classForName(className); 209 var obj = new JOObject(className); 210 clazz.apply(obj, args.slice(1)); 211 injectprototype(obj,clazz); 212 return obj; 213 }; 214 215 oofactory.classForName = function (className) { 216 if (!className || JOObject.className === className) return JOObject; 217 pkg = pkg || new Package(oofactory._); 218 return pkg.classForName(className); 219 }; 220 221 return oofactory; 222 });
自动化测试例子,可以参考学习:
1 define([ 2 'underscore', 3 'oo', 4 'require', 5 'boot', 6 './oo_package/oo_base', 7 './oo_package/oo_sub' 8 ], 9 function (_, oo, require, sub) { 10 'use strict'; 11 12 describe("[oo test]", function () { 13 14 beforeEach(function () { 15 spyOn(oo, 'register'); 16 }); 17 18 it("register类注册测试", function () { 19 expect(_.isObject(oo._.xxxxx.OOTest.OoBase)).toBe(true); 20 expect(_.isObject(oo._.xxxxx.OOTest.OoSub)).toBe(true); 21 }); 22 23 it("new-createClass创建类", function () { 24 var b = oo.createClass("xxxxx.OOTest.OoBase", 1, 2); 25 expect(_.isObject(b)).toBe(true); 26 expect(b.getInitParamater()).toEqual([1, 2]); 27 }); 28 29 it("private私有方法", function () { 30 var b = oo.createClass("xxxxx.OOTest.OoBase"); 31 expect(b.baseGet()).toEqual("base"); 32 var c = oo.createClass("xxxxx.OOTest.OoSub"); 33 expect("baseGet" in c).toBe(false); 34 expect("getInitParamater" in c).toBe(false); 35 }); 36 37 it("virtual继承多态", function () { 38 var b = oo.createClass("xxxxx.OOTest.OoBase"); 39 expect(b.virtualGet()).toEqual("base");//多态 40 var c = oo.createClass("xxxxx.OOTest.OoSub"); 41 expect(c.virtualGet()).toEqual("sub");//继承+多态 42 }); 43 44 it("base父类调用", function () { 45 var b = oo.createClass("xxxxx.OOTest.OoSub"); 46 expect(b.baseGetName()).toEqual("base");//调用父类方法 47 expect(b.base().virtualGet()).toEqual("base"); 48 }); 49 50 it("over覆盖父类调用", function () { 51 var b = oo.createClass("xxxxx.OOTest.OoSub"); 52 expect(b.getName()).toEqual("sub");//调用父类方法 53 expect(b.base().getName()).toEqual("base"); 54 }); 55 56 it("abstract抽象方法", function () { 57 var b = oo.createClass("xxxxx.OOTest.OoSub"); 58 expect(b.trueVirtual).toThrowError(TypeError, "trueVirtual");//抽象方法 59 }); 60 61 it(":base(1,2)初始化父类构造函数测试", function () { 62 var b = oo.createClass("xxxxx.OOTest.OoSub", "a", "b"); 63 expect(b.base().getInitParamater()).toEqual(["a", "b"]); 64 }); 65 66 it("base.调用基类方法", function () { 67 var b = oo.createClass("xxxxx.OOTest.OoSub"); 68 expect(b.base("xxxxx.OOTest.OoBase").getName()).toEqual("base"); 69 expect(b.base().getName()).toEqual("base"); 70 }); 71 72 it("createInstance静态构造", function () { 73 var a = oo.classForName("xxxxx.OOTest.OoBase").createInstance(1, 2); 74 expect(_.isObject(a)).toBe(true); 75 expect(a.getInitParamater()).toEqual([1, 2]); 76 //expect(a.privateGet()).toEqual("base");//非虚函数 77 expect(a.virtualGet()).toEqual("base");//多态 78 var b = oo.classForName("xxxxx.OOTest.OoSub").createInstance(); 79 expect(b.baseGetName()).toEqual("base");//调用父类方法 80 // expect(b.privateGet()).toEqual("base"); 81 expect(b.virtualGet()).toEqual("sub");//继承+多态 82 expect(b.trueVirtual).toThrowError(TypeError, "trueVirtual");//抽象方法 83 }); 84 85 it("static静态方法", function () { 86 expect(oo.classForName("xxxxx.OOTest.OoSub").parent).toEqual("xxxxx.OOTest.OoBase"); 87 }); 88 89 it("instanceof实例", function () { 90 expect(oo.createClass("xxxxx.OOTest.OoSub").instanceOf("xxxxx.OOTest.OoSub")).toBe(true); 91 expect(oo.createClass("xxxxx.OOTest.OoSub").instanceOf("xxxxx.OOTest.OoBase")).toBe(true); 92 expect(oo.createClass("xxxxx.OOTest.OoSub").instanceOf("JOObject")).toBe(true); 93 }); 94 95 it("in方法", function () { 96 expect("getName" in oo.createClass("xxxxx.OOTest.OoSub")).toBe(true); 97 expect("getName" in oo.createClass("xxxxx.OOTest.OoSub").base()).toBe(true); 98 }); 99 100 it("getType类名", function () { 101 expect(oo.createClass("xxxxx.OOTest.OoSub").className).toEqual("xxxxx.OOTest.OoSub"); 102 }); 103 104 it("getType继承类名测试", function () { 105 var b = oo.createClass("xxxxx.OOTest.OoSub"); 106 expect(b.getClassName()).toEqual("xxxxx.OOTest.OoSub"); 107 expect(b.base().getClassName()).toEqual("xxxxx.OOTest.OoBase"); 108 }); 109 110 afterEach(function () { 111 }); 112 return {}; 113 }); 114 window.onload(); 115 });
posted on 2016-01-12 16:19 learning... 阅读(295) 评论(0) 收藏 举报
浙公网安备 33010602011771号