最近翻书复习了下基础知识,感觉书上的面向对象的例子用起来不是很顺手
所以自己改了下,纯粹练手,有意见的请拍砖,当然最好能给出更好的例子。
- JScript code
var $class = (function(){ var guid = 0, classMap = {}, caller = null, callStack = []; return { create : createClass } //------------------------[辅助函数部分]------------------------ /** * 创建新类. * @param {constructor}superClass 超类构造器,该类必须由$class.create创建 * @param {Json}proto 类原型 * @return {constructor} */ function createClass(superClass, proto){ var isSuperValid = superClass instanceof Function && superClass.prototype && superClass.prototype.init instanceof Function; superClass = isSuperValid ? superClass : null; var superProto = superClass ? superClass.prototype : null; //定义类构造函数 var klass = function() { var args = [].slice.call(arguments); //执行父类构造函数. if(superClass){ superClass.apply(this, args); } //若自己的原型中有init方法,执行init if(klass.prototype.hasOwnProperty('init')){ klass.prototype.init.apply(this, args); } }; //定义类原型 var klassProto = getClassProto(superProto, proto); klassProto.constructor = klass; klass.prototype = klassProto; //返回类 return klass; } /** * 获取类原型. * @param {json}superProto 超类原型 * @param {Json}overwrites 需要重写方法 * @return {json} */ function getClassProto(superProto, overwrites) { var i, F, proto, classId = getGuid(); if(superProto){ F = function(){}; F.prototype = superProto; proto = new F(); }else{ proto = getDefaultProto(); } //用overwrites中方法覆盖原型中的方法 for(i in overwrites){ if(overwrites.hasOwnProperty(i)){ proto[i] = overwrites[i]; } } //修复IE中for in不能遍历toString、valueOf等属性的Bug if(document.all){ var len, method, methods = ['toString', 'valueOf']; for(i=0, len = methods.length; i < len; i++){ method = methods[i]; if( overwrites.hasOwnProperty(method) ){ proto[method] = overwrites[method]; } } } //注册类关系 proto.classId = classId; regClass(proto, superProto); //确保原型中含有必要的原型方法 addMastHasMethods(proto); return proto; } /** * 获取默认原型. * @return {json} */ function getDefaultProto(){ return { init : function(){}, callSuper : callSuper }; } /** * 调用超类方法. * @param {String}methodName 方法名 * @return */ function callSuper(methodName){ caller = (caller === null ? this : caller); var curClsId = callStack.length > 0 ? callStack[callStack.length - 1] : this.classId; var args = [].slice.call(arguments, 1), parent = getParent(curClsId), ret; if(parent && parent[methodName]){ callStack.push(parent.classId); try{ ret = parent[methodName].apply(caller, args); }catch(e){ alert(e); } callStack.pop(); } //调用完毕后将调用上下文清空 if(callStack.length === 0){ caller = null; } return ret; } /** * 将类信息注册到类记录表中. * @param {json}proto 类原型. * @param {json}parent 超类原型 */ function regClass(proto, superProto){ var classId = proto.classId; classMap[classId] = { id : classId, proto : proto, parent: superProto }; } /** * 检查原型链中是否有必须要实现的方法,没有的话,向原型中添加. * @param {json}proto */ function addMastHasMethods(proto){ var i, dftProto = getDefaultProto(); for(i in dftProto){ if(dftProto.hasOwnProperty(i) && !proto[i]){ proto[i] = dftProto[i]; } } } /** * 获取guid. * @return {int} */ function getGuid(){ return guid++; } /** * 获取超类原型. * @param {int}classId 类ID * @return {json} 超类原型, 若存在返回null. */ function getParent(classId){ var record = classMap[classId]; return record ? record.parent : null; } })(); var Man = $class.create(null, { init : function(cfg){ this.name = cfg.name; this.age = cfg.age; }, say : function(){ alert('my name is:' + this.name + ", " + this.age); }, toString : function(){ return ( 'name: ' + this.name + ', age: ' + this.age ); } }); var Student = $class.create(Man, { init : function(cfg){ //执行此方法前会自动调用Man.init this.stuNum = cfg.stuNum; }, say : function(){ this.callSuper('say'); //调用父类方法 alert("i'm a student, my student number is " + this.stuNum); }, toString : function(){ return ( this.callSuper('toString') + ', stuNum: ' + this.stuNum ); } }); window.onload = function(){ var m1 = new Man({name : '张三', age: 20}), s1 = new Student({ name : '王五', age : 22, stuNum : 'no-1' }); m1.say(); s1.say(); alert(m1.toString() + "\n" + s1.toString()); };