Ruby's Louvre

每天学习一点点算法

导航

mass Framework lang模块 v4

v3没有公开出来,只是一些函数进行升级。v4则是对语言链对象的实现进行大升级,第一次链机制的实现可见这里

这是把$.lang改造成一个工厂方法,通过它吐出语言链对象(Chain)的实例。这个语言链对象有两个重要属性,target与type,几乎所有方法都是通过它俩判定是否使用原生方法还是扩展的方法。

 var arrayLike = $.oneObject("NodeList,Arguments,Object");
    //这只是一个入口
    $.lang = function(obj, type){
        return adjust(new Chain, obj, type)
    }
    //调整Chain实例的重要属性
    function adjust(chain, obj, type){
        type = type || $.type(obj);
        if(arrayLike[type] && isFinite(obj.length)){
            obj = $.slice(obj);
            type = "Array";
        }
        chain.target = obj;
        chain.type = type;
        return chain
    }
    //语言链对象
    var Chain = function(){ }
    Chain.prototype = {
        constructor: Chain,
        valueOf:function(){
            return this.target;
        },
        toString:function(){
            return this.target + "";
        },
        value: function(){
            return this.target;
        }
    };

所谓的扩展包就是$.String, $.Array, $.Number, $.Object这四个helper方法的对象传参,但这四个方法不但可以传对象,还可以传字符串,它内部会转换成字符串数组。这个数组包含的是这个数据类型已有一些常用方法名,它也会把它们绑到链对象的原型上。

                $.String(StringExt);//添加String扩展包
                $.String(NativeStringMethodList);//添加String原生方法,这是一个字符串,所有方法名都是用逗号隔开
                $.Array(ArrayExt);//添加Array扩展包
                $.Array(NativeArrayMethodList);//添加Array原生方法
                $.Number(NumberExt);//添加Number扩展包
                $.Number(NativeNumberMethodList);//添加Number原生方法
                $.Object(ObjectExt);//添加Object扩展包
                $.Object(NativeObjectMethodList);//添加Object原生方法

下面是四大helper的真身,通过它们来装备语言链对象的原型。


  var retouch = function(method){//函数变换,静态转原型
        return function(){
            [].unshift.call(arguments,this)
            return method.apply(null,arguments)
        }
    }
    var proto = Chain.prototype;
    //构建语言链对象的四大helper:$.String, $.Array, $.Number, $.Object
    "String,Array,Number,Object".replace($.rword, function(type){
        $[type] = function(ext){
            var isNative = typeof ext == "string",
            methods =  isNative ?  ext.match($.rword) : Object.keys(ext);
            methods.forEach(function(name){
                $[type][name] = isNative ? function(obj){
                    return obj[name].apply(obj,$.slice(arguments,1) );
                } :  ext[name];
                proto[name] = function(){
                    var target = this.target;
                    if( target == null){
                        return this;
                    }else{
                        var method = isNative ? target[name] : retouch( $[this.type][name] ),
                        next = this.target = method.apply( target, arguments ),
                        type = $.type( next );
                        if( type === this.type){
                            return this;
                        }else{
                            return adjust(this, next, type)
                        }
                    }
                }
            });
        }
    });

至于这些扩展包怎么用,无须多言吧。不过注意,里面都是静态方法哦!


    var NumberExt = {
        times: function(target, fn, bind) {
            for (var i=0; i < target; i++)
                fn.call(bind, i);
            return target;
        },
        //确保数值在[n1,n2]闭区间之内,如果超出限界,则置换为离它最近的最大值或最小值
        constrain: function(target, n1, n2){
            var a = [n1, n2].sort();
            if(target < a[0]) target = a[0];
            if(target > a[1]) target = a[1];
            return target;
        },
        //求出距离原数最近的那个数
        nearer: function(target, n1, n2){
            var diff1 = Math.abs(target - n1),
            diff2 = Math.abs(target - n2);
            return diff1 < diff2 ? n1 : n2
        },
        upto: function(target, number, fn, scope) {
            for (var i=target+0; i <= number; i++)
                fn.call(scope, i);
            return target;
        },
        downto: function(target, number, fn, scope) {
            for (var i=target+0; i >= number; i--)
                fn.call(scope, i);
            return target;
        },
        round: function(target, base) {
            if (base) {
                base = Math.pow(10, base);
                return Math.round(target * base) / base;
            } else {
                return Math.round(target);
            }
        }
    }
    "padLeft,padRight".replace($.rword, function(name){
        NumberExt[name] = $.String[name];
    });
    "abs,acos,asin,atan,atan2,ceil,cos,exp,floor,log,pow,sin,sqrt,tan".replace($.rword,function(name){
        NumberExt[name] = Math[name];
    });
    $.Number(NumberExt);
    $.Number("toFixed,toExponential,toPrecision,toJSON")

一些示例:

            $.require("lang",function(){
                $.lang("aaa_bbb").toLowerCase().capitalize().camelize()
                .split("").forEach(function(s){
                    $.log(s)// A a a B b b
                });
                $.log( $.lang(null).toInt().value() ) //null
                $.log($.String.toLowerCase("AAA")) //aaa
            })
〈pre〉
〈p〉模块已经更新到github上了。〈/p〉

posted on 2012-03-17 21:41  司徒正美  阅读(1448)  评论(0编辑  收藏  举报