1 /** 2 * Hilo 3 * Copyright 2015 alibaba.com 4 * Licensed under the MIT License 5 */ 6 7 /** 8 * @language=zh 9 * 创建类示例: 10 * <pre> 11 * var Bird = Hilo.Class.create({ 12 * Extends: Animal, 13 * Mixes: EventMixin, 14 * constructor: function(name){ 15 * this.name = name; 16 * }, 17 * fly: function(){ 18 * console.log('I am flying'); 19 * }, 20 * Statics: { 21 * isBird: function(bird){ 22 * return bird instanceof Bird; 23 * } 24 * } 25 * }); 26 * 27 * var swallow = new Bird('swallow'); 28 * swallow.fly(); 29 * Bird.isBird(swallow); 30 * </pre> 31 * @namespace Class是提供类的创建的辅助工具。 32 * @static 33 * @module hilo/core/Class 34 */ 35 var Class = (function(){ 36 37 /** 38 * @language=zh 39 * 根据参数指定的属性和方法创建类。 40 * @param {Object} properties 要创建的类的相关属性和方法。主要有: 41 * <ul> 42 * <li><b>Extends</b> - 指定要继承的父类。</li> 43 * <li><b>Mixes</b> - 指定要混入的成员集合对象。</li> 44 * <li><b>Statics</b> - 指定类的静态属性或方法。</li> 45 * <li><b>constructor</b> - 指定类的构造函数。</li> 46 * <li>其他创建类的成员属性或方法。</li> 47 * </ul> 48 * @returns {Object} 创建的类。 49 */ 50 var create = function(properties){ 51 properties = properties || {}; 52 var clazz = properties.hasOwnProperty('constructor') ? properties.constructor : function(){}; 53 implement.call(clazz, properties); 54 return clazz; 55 } 56 57 /** 58 * @language=zh 59 * @private 60 */ 61 var implement = function(properties){ 62 var proto = {}, key, value; 63 for(key in properties){ 64 value = properties[key]; 65 if(classMutators.hasOwnProperty(key)){ 66 classMutators[key].call(this, value); 67 }else{ 68 proto[key] = value; 69 } 70 } 71 72 mix(this.prototype, proto); 73 }; 74 75 var classMutators = /** @ignore */{ 76 Extends: function(parent){ 77 var existed = this.prototype, proto = createProto(parent.prototype); 78 //inherit static properites 79 mix(this, parent); 80 //keep existed properties 81 mix(proto, existed); 82 //correct constructor 83 proto.constructor = this; 84 //prototype chaining 85 this.prototype = proto; 86 //shortcut to parent's prototype 87 this.superclass = parent.prototype; 88 }, 89 90 Mixes: function(items){ 91 items instanceof Array || (items = [items]); 92 var proto = this.prototype, item; 93 94 while(item = items.shift()){ 95 mix(proto, item.prototype || item); 96 } 97 }, 98 99 Statics: function(properties){ 100 mix(this, properties); 101 } 102 }; 103 104 /** 105 * @language=zh 106 * @private 107 */ 108 var createProto = (function(){ 109 if(Object.__proto__){ 110 return function(proto){ 111 return {__proto__: proto}; 112 } 113 }else{ 114 var Ctor = function(){}; 115 return function(proto){ 116 Ctor.prototype = proto; 117 return new Ctor(); 118 } 119 } 120 })(); 121 122 /** 123 * @language=zh 124 * 混入属性或方法。 125 * @param {Object} target 混入目标对象。 126 * @param {Object} source 要混入的属性和方法来源。可支持多个来源参数。 127 * @returns {Object} 混入目标对象。 128 */ 129 var mix = function(target){ 130 for(var i = 1, len = arguments.length; i < len; i++){ 131 var source = arguments[i], defineProps; 132 for(var key in source){ 133 var prop = source[key]; 134 if(prop && typeof prop === 'object'){ 135 if(prop.value !== undefined || typeof prop.get === 'function' || typeof prop.set === 'function'){ 136 defineProps = defineProps || {}; 137 defineProps[key] = prop; 138 continue; 139 } 140 } 141 target[key] = prop; 142 } 143 if(defineProps) defineProperties(target, defineProps); 144 } 145 146 return target; 147 }; 148 149 try{ 150 var defineProperty = Object.defineProperty, 151 defineProperties = Object.defineProperties; 152 defineProperty({}, '$', {value:0}); 153 }catch(e){ 154 if('__defineGetter__' in Object){ 155 defineProperty = function(obj, prop, desc){ 156 if('value' in desc) obj[prop] = desc.value; 157 if('get' in desc) obj.__defineGetter__(prop, desc.get); 158 if('set' in desc) obj.__defineSetter__(prop, desc.set); 159 return obj; 160 }; 161 defineProperties = function(obj, props){ 162 for(var prop in props){ 163 if(props.hasOwnProperty(prop)){ 164 defineProperty(obj, prop, props[prop]); 165 } 166 } 167 return obj; 168 }; 169 } 170 } 171 172 return {create:create, mix:mix}; 173 174 })(); 175