[转帖]Mootools源码分析-01 -- Native

原帖地址:http://space.flash8.net/space/?18713/viewspace-399937.html

原作者:我佛山人

 

//框架名,对象
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 ōbject = initialize || legacy;

    
//设置构造器
    object.constructor = Native;
    
//用于$type方法的取值
    object.$family = {name: 'native'};
    
//继承legacy
    if (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数组化,一种技巧
            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']);

 

posted @ 2009-10-22 10:21  webgis松鼠  阅读(418)  评论(1)    收藏  举报