MooTools源码分析一 —— Native
转自: http://mooui.com/blog/view.aspx?id=1
// 框架名,对象var MooTools = {'version' : '1.2dev', // 里程碑版本'build' : '1519' // trac系统每次change的版本号};/* * Native 是对内置或将之作为内置的对象的包装化 */var Native = function(options) {/* * 这种写法随处可见,根据ECMA规范,||运算会自动将两侧表达式转化为布尔值, * 仅当表达式为0/undefined/null/false时为假,而且||的特性是当前表达式为false时才会执行后表达式, * 用在这里的目的是使没传参时设置options的默认值,以避免下面的代码出错 */options = options || {};// 继续上面的写法,设默认值为一空方法,用于add中执行implement的后续操作var afterImplement = options.afterImplement || function() {};// 方法静态化标记,为真时实例方法将被复制到类名下作为静态方法,此时静态方法的第一个参数会被作为实例方法内的this执行var generics = options.generics;// 用!==比较,当且仅当generics为false时为false,其它值按true处理,这是比较提高可靠性的一种处理方式generics = (generics !== false);// 用于对内置对象包装时的原对象var legacy = options.legacy;// Prototype风格的初始化方法var initialize = options.initialize;// 是否保护原对象的原型方法,以免被继承的同名方法覆盖var protect = options.protect;// 指定类名,以用于$type方法的取值var name = options.name;// 又是||的写法,在不提供初始化方法时直接使用内置的对象作为原型var object = initialize || legacy;// 设置构造器object.constructor = Native;// 用于$type方法的取值object.$family = {name : 'native'};// 继承legacyif (legacy && initialize)object.prototype = legacy.prototype;object.prototype.constructor = object;if (name) {// 全部用小写,可以避免大小写敏感,当然可以换成大写,只是大写不美观、不直观var family = name.toLowerCase();// 写在原型链上object.prototype.$family = {name : family};// 类型化,现在可以使用object.type(object1)判断object与object1是否同一家族/类型Native.typize(object, family);}// 总的为对象添加方法的处理var add = function(obj, name, method, force) {// 仅当不指定对象受保护,或指定强制覆盖或原对象原型中不存在该方法时添加if (!protect || force || !obj.prototype[name])obj.prototype[name] = method;// 方法静态化,此时的静态方法的第一个参数会被作为实例方法中的this执行if (generics)Native.genericize(obj, name, protect);// 后续处理afterImplement.call(obj, name, method);return obj;};// implement静态方法object.implement = function(a1, a2, a3) {if (typeof a1 == 'string')return add(this, a1, a2, a3);for (var p in a1)add(this, p, a1[p], a2);// 返回当前对象可以使方法支持链式写法,如object.implement(...).implement(...),jQueryer的最爱return this;};// 实现方法别名的静态方法object.alias = function(a1, a2, a3) {if (typeof a1 == 'string') {a1 = this.prototype[a1];if (a1)add(this, a2, a1, a3);} else {// 使alias支持object.alias({a : 'a1', b : 'b1'});这样的多个方法进行别名处理for (var a in a1)this.alias(a, a1[a], a2);}// 使支持链式写法return this;};return object;};// 用于同时对多个对象进行扩展实现,子对象须被Native化,或者实现了名为implement的静态方法Native.implement = function(objects, properties) {for (var i = 0, l = objects.length; i < l; i++)objects[i].implement(properties);};// 方法静态化Native.genericize = function(object, property, check) {if ((!check || !object[property]) && typeof object.prototype[property] == 'function')object[property] = function() {// 将arguments数组化,一种技巧.(注:arguments并非数组而只是一个类似数组的对象)var args = Array.prototype.slice.call(arguments);// 将第一个参数作为原来实例方法的this指向return object.prototype[property].apply(args.shift(), args);};};// 使类支持类型比较,闭包使用技巧Native.typize = function(object, family) {if (!object.type)object.type = function(item) {return ($type(item) === family);};};// 用于同时对多个对象进行别名操作Native.alias = function(objects, a1, a2, a3) {for (var i = 0, j = objects.length; i < j; i++)objects[i].alias(a1, a2, a3);};/* * 模块化写法 * 因为js中的变量作用域只存在于function和with中,此处使用模块化写法避免全局变量污染,就地执行匿名方法 * 使Boolean/Native/Object支持类型比较操作 */(function(objects) {for (var name in objects)Native.typize(objects[name], name.toLowerCase());})({'boolean' : Boolean,'native' : Native,'object' : Object});/* * 模块化写法 * 对下列内置类型进行Native化包装,使之支持类型化,别名,继承等 */(function(objects) {// 其实new Native跟Native的结果应该是一样的,但是有时为了安全起见,用new能避免很多无法考虑的数据引用for (var name in objects)new Native({name : name,initialize : objects[name],protect : true});})({'String' : String,'Function' : Function,'Number' : Number,'Array' : Array,'RegExp' : RegExp,'Date' : Date});/* * 模块化写法 * 让数组和字符串的实例方法静态化(因为数组和字符串的应用比较多) 现在可以使用Array.pop */(function(object, methods) {for (var i = 0, l = methods.length; i < l; i++)Native.genericize(object, methods[i], true);// 虽然是匿名方法,但是仍然可以通过arguments.callee找到指向,这里return使(function(){})()()()()的写法成为可能return arguments.callee;})(Array, ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join','slice', 'toString', 'valueOf', 'indexOf', 'lastIndexOf'])(String, ['charAt', 'charCodeAt','concat', 'indexOf', 'lastIndexOf', 'match', 'replace', 'search', 'slice', 'split','substr', 'substring', 'toLowerCase', 'toUpperCase', 'valueOf']);