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〉