1 2 /** 3 * @namespace Class是提供类的创建的辅助工具。 4 * @static 5 * @module hilo/core/Class 6 */ 7 var Class = (function(){ 8 9 /** 10 * 此方法是在Hilo中创建类的主要方法。 11 * @param {Object} properties 要创建的类的相关属性和方法。主要有: 12 * <ul> 13 * <li><b>Extends</b> - 指定要继承的父类。</li> 14 * <li><b>Mixes</b> - 指定要混入的成员集合对象。</li> 15 * <li><b>Statics</b> - 指定类的静态属性或方法。</li> 16 * </ul> 17 * @returns {Object} 创建好的类。 18 */ 19 var create = function(properties){ 20 properties = properties || {}; 21 var clazz = properties.hasOwnProperty('constructor') ? properties.constructor : function(){}; 22 implement.call(clazz, properties); 23 return clazz; 24 } 25 26 /** 27 * @private 28 */ 29 var implement = function(properties){ 30 var proto = {}, key, value; 31 for(key in properties){ 32 value = properties[key]; 33 if(classMutators.hasOwnProperty(key)){ 34 classMutators[key].call(this, value); 35 }else{ 36 proto[key] = value; 37 } 38 } 39 40 mix(this.prototype, proto); 41 }; 42 43 var classMutators = /** @ignore */{ 44 Extends: function(parent){ 45 var existed = this.prototype, proto = createProto(parent.prototype); 46 //inherit static properites 47 mix(this, parent); 48 //keep existed properties 49 mix(proto, existed); 50 //correct constructor 51 proto.constructor = this; 52 //prototype chaining 53 this.prototype = proto; 54 //shortcut to parent's prototype 55 this.superclass = parent.prototype; 56 }, 57 58 Mixes: function(items){ 59 items instanceof Array || (items = [items]); 60 var proto = this.prototype, item; 61 62 while(item = items.shift()){ 63 mix(proto, item.prototype || item); 64 } 65 }, 66 67 Statics: function(properties){ 68 mix(this, properties); 69 } 70 }; 71 72 /** 73 * @private 74 */ 75 var createProto = (function(){ 76 if(Object.__proto__){ 77 return function(proto){ 78 return {__proto__: proto}; 79 } 80 }else{ 81 var Ctor = function(){}; 82 return function(proto){ 83 Ctor.prototype = proto; 84 return new Ctor(); 85 } 86 } 87 })(); 88 89 /** 90 * 混入属性或方法。 91 * @param {Object} target 混入目标对象。 92 * @returns {Object} 混入目标对象。 93 */ 94 var mix = function(target){ 95 for(var i = 1, len = arguments.length; i < len; i++){ 96 var source = arguments[i], defineProps; 97 for(var key in source){ 98 var prop = source[key]; 99 if(prop && typeof prop === 'object'){ 100 if(prop.value !== undefined || typeof prop.get === 'function' || typeof prop.set === 'function'){ 101 defineProps = defineProps || {}; 102 defineProps[key] = prop; 103 continue; 104 } 105 } 106 target[key] = prop; 107 } 108 if(defineProps) defineProperties(target, defineProps); 109 } 110 111 return target; 112 }; 113 114 try{ 115 var defineProperty = Object.defineProperty, 116 defineProperties = Object.defineProperties; 117 defineProperty({}, '$', {value:0}); 118 }catch(e){ 119 if('__defineGetter__' in Object){ 120 defineProperty = function(obj, prop, desc){ 121 if('value' in desc) obj[prop] = desc.value; 122 if('get' in desc) obj.__defineGetter__(prop, desc.get); 123 if('set' in desc) obj.__defineSetter__(prop, desc.set); 124 return obj; 125 }; 126 defineProperties = function(obj, props){ 127 for(var prop in props){ 128 if(props.hasOwnProperty(prop)){ 129 defineProperty(obj, prop, props[prop]); 130 } 131 } 132 return obj; 133 }; 134 } 135 } 136 137 return {create:create, mix:mix}; 138 139 })(); 140