全部博文(372)
2012年(372)
分类: 虚拟化
2012-03-18 19:46:28
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") |
一些示例: