由于js的对象已经有很多解释,决定读一段关于制作js class库的源码,以加深印象。
(function(){
'use strict';
// saving constants
var VERSION = '1.0';
var ORIGINAL = window.Class;
// creating global class variable
var Class = window.Class = function (obj) {
obj = obj || {};
// call initialize if given
var constructor = function () {
return (this.initialize) ? this.initialize.apply(this, arguments) : self;
};
// adds implement to the class itself
if(obj.implement) {
var self = window === this ? copy(constructor.prototype) : this; // copy是Object.create
var imp = obj.implement; // 抽取obj.implement,其是一个Class对象数组
remove(obj, 'implement'); // 抽取完后删除obj的implement属性
obj = extend(obj, implement(imp)); // 保存数组中所有Class对象属性
}
// assign prototypes
constructor.prototype = copy(obj); // 复制obj,并将prototype链相连
// assign correct constructor for correct instanceof comparison
constructor.constructor = constructor; // 将constructor绑定为自己
// save initial object as parent so it can be called by this.parent
constructor._parent = copy(obj); // 将parent设定为obj的copy
// attaching class properties to constructor
for(var i = 0, values = ['extend', 'implement', 'getOptions', 'setOptions']; i < values.length; i++) {
constructor[values[i]] = Class[values[i]]; // 将Class的原生方法拓展到constructor上
}
return constructor; // 返回这个constructor,即返回了一个新的类
};
// adding class method extend
Class.extend = function (obj) {
var self = this; // 拓展方法
// check if implement is passed through extend
if(obj.implement) {
this.prototype = extend(this.prototype, implement(obj.implement)); // 拓展prototype链,如果有implement状态时
// remove implement from obj
remove(obj, 'implement'); // 消除obj的implement属性,防止后面拓展的时候加上
}
// check if we should invoke parent when its called within a method
for(var key in obj) { // 判断该obj是否是函数且当中含有parent字符,即判断是否为一个类
obj[key] = typeof obj[key] === 'function' && /parent/.test(obj[key].toString()) ? (function (method, name) {
return function () {
this.parent = self._parent[name]; // 监测到含有this.parent()等字样时,就会将this.parent指向原本的parent
return method.apply(this, arguments);
}; //有则返回一个能够执行该方法,并且将parent规定为当前对象的_parent
})(obj[key], key) : obj[key] // 要么返回传入的参数后生成的类,要么返回原本属性
}
// assign new parent
this._parent = extend(this._parent, obj, true); // 拓展自身父类
// assign new prototype
this.prototype = extend(this.prototype, obj); // 拓展自身方法
// return the class if its assigned
return this;
};
// adding class method implement
Class.implement = function (array) {
return this.prototype = extend(this.prototype, implement(array)); // 拓展方法
};
// gets options from constructor
Class.getOptions = function () {
return this.prototype.options || {}; // 返回prototype中options属性的值
};
// sets options for constructor
Class.setOptions = function (options) {
return this.prototype.options = extend(this.prototype.options, options); // 设定prototype中options的值
};
// preventing conflicts
Class.noConflict = function () {
// reassign original Class obj to window
window.Class = ORIGINAL;
return Class; // noConflict
};
// returns current running version
Class.version = VERSION;
// helper for assigning methods to a new prototype
function copy(obj) {
var F = function () {};
F.prototype = obj.prototype || obj;
return new F();
}
// insures the removal of a given method name
function remove(obj , name, safe){
// if save is active we need to copy all attributes over.
if(safe) {
var safeObj = {};
for(var key in obj) {
if(key !== name) safeObj[key] = obj[key]; // safe代表返回新对象
}
} else {
delete obj[name]; // 直接删除
}
return safeObj || obj; // 请选择你的结局
}
// helper for merging two object with each other
function extend(oldObj, newObj, preserve) {
// failsave if something goes wrong
if(!oldObj || !newObj) return oldObj || newObj || {};
// make sure we work with copies
oldObj = copy(oldObj); // 确保操纵的是一个copy,不影响原本的对象,并返回新对象
newObj = copy(newObj);
for(var key in newObj) {
if(Object.prototype.toString.call(newObj[key]) === '[object Object]') {
extend(oldObj[key], newObj[key]); // 深度遍历
} else {
// if preserve is set to true oldObj will not be overwritten by newObj if
// oldObj has already a method key
oldObj[key] = (preserve && oldObj[key]) ? oldObj[key] : newObj[key]; // 有preserve则不替换原本具有的属性
}
}
return oldObj; // 返回旧对象
}
// helper for implementing other classes or objects
function implement(array) {
var collection = {};
for(var i = 0; i < array.length; i++) {
// check if a class is implemented and save its prototype
if(typeof(array[i]) === 'function') array[i] = array[i].prototype; // 保存原型
// safely remove initialize
var safe = remove(array[i], 'initialize', true); // 去掉initialize属性
// we use implement again if array has the apropriate methiod, otherwise we extend
if(safe.implement) {
collection = implement(safe.implement); // 如果还有implement属性,继续处理
} else {
collection = extend(collection, safe); // 没有则将属性拓展
}
}
return collection; //返回新的包含所有方法的对象
}
})();
由于注释已经标在上面,后面只挑几个关键点
function copy(obj) {
var F = function () {};
F.prototype = obj.prototype || obj;
return new F();
}
这个是典型的原型继承方式,通过创造一个prototype连向指定对象的空对象,这样即避免重新实例化属性,也能取到这个属性,Object.create
prototype放方法,实例化属性,非常清晰。
function extend(oldObj, newObj, preserve) {
// failsave if something goes wrong
if(!oldObj || !newObj) return oldObj || newObj || {};
// make sure we work with copies
oldObj = copy(oldObj); // 确保操纵的是一个copy,不影响原本的对象,并返回新对象
newObj = copy(newObj);
for(var key in newObj) {
if(Object.prototype.toString.call(newObj[key]) === '[object Object]') {
extend(oldObj[key], newObj[key]); // 深度遍历
} else {
// if preserve is set to true oldObj will not be overwritten by newObj if
// oldObj has already a method key
oldObj[key] = (preserve && oldObj[key]) ? oldObj[key] : newObj[key]; // 有preserve则不替换原本具有的属性
}
}
return oldObj; // 返回旧对象
}
继承对象还有另一个方法,就是直接将属性遍历安放在上面,extend。