Underscore骨骼

上次写过一篇QWrap骨骼的文章,个人认为,想要了解一个库或框架,首先从他的核心思想入手,理解其思想,那么剩余的就仅仅是方法的堆砌。近年比较火的一个jsMVC框架backbone他的核心强依赖库为underscore

抽空提取了一下他的骨骼,其实主要就是他的链式操作的实现,别个剩下的就是具体函数的实现了,当然对于Underscore函数式也是它的最大亮点,可以好好看下函数的实现。

<! DOCTYPE html >
< html >
< head >
< title >  Underscore骨骼  < / title>
< / head>
< body >
< script type = " text/javascript " >
//  Underscore骨骼
( function  () {
    
var  root  =   this ;
    
    
    
var  breaker  =  {};

    
var  ArrayProto  =  Array.prototype, ObjProto  =  Object.prototype;

    
var  nativeForEach     =  ArrayProto.forEach,
        nativeMap        
=  ArrayProto.map,
        nativeFilter    
=  ArrayProto.filter,
        nativeKeys        
=  Object.keys;

    
var  slice             =  ArrayProto.slice,
        unshift            
=  ArrayProto.unshift,
        hasOwnProperty  
=  ObjProto.hasOwnProperty;

    
//  构造函数
     var  _  =   function  (obj) {  return   new  wrapper(obj); };

    
//  向全局暴露接口
    root._  =  _;

    
//  类型检测
    _.isNumber  =   function  (obj) {
        
return   !! (obj  ===   0   ||  (obj  &&  obj.toExponential  &&  obj.toFixed));
    };
    _.isFunction 
=   function  (obj) {
        
return   !! (obj  &&  obj.constructor  &&  obj.call  &&  obj.apply);
    };

    
//  遍历扩展
     var  each  =  _.each  =  _.forEach  =   function  (obj, iterator, context) {
        
if  (obj  ===   null return ;
        
        
if  (nativeForEach  &&  obj.forEach  ===  nativeForEach) {
            obj.forEach(iterator, context);
        } 
else   if  (_.isNumber(obj.length)) {
            
for  ( var  i  =   0 , l  =  obj.length; i  <  l; i ++ ) {
                
if  (iterator.call(context, obj[i], i, obj)  ===  breaker)  return
            }
        } 
else  {
            
for  ( var  key  in  obj) {
                
if  (hasOwnProperty.call(obj, key)) {
                    
if  (iterator.call(context, obj[key], key, obj)  ===  breaker)  return
                } 
            }
        }
    };

    
//  返回对象上面的函数名
    _.functions  =  _.methods  =   function  (obj) {
        
return  _.filter(_.keys(obj),  function  (key) {  return  _.isFunction(obj[key])}).sort();
    };

    
//  过滤数组
    _.filter  =  _.select  =   function  (obj, iterator, context) {
        
var  results  =  [];
        
if  (obj  ==   null return  results; 
        
if  (nativeFilter  &&  obj.filter  ===  nativeFilter)  return  obj.filter(iterator, context);
        
        each(obj, 
function  (value, index, list) {
            
if  (iterator.call(context, value, index, list)) results[results.length]  =  value; 
        });
        
return  results;
    };

    
//  获取key值
    _.keys  =  nativeKeys  ||   function  (obj) {
        
if  (obj  !==  Object(obj))  throw   new  TypeError( ' Invalid object ' );
        
var  keys  =  [];
        
for  ( var  key  in  obj)  if  (hasOwnProperty.call(obj, key)) keys[keys.length]  =  key;
        
return  keys;
    };

    
//  用于实验的map方法
    _.map  =   function  (obj, iterator, context) {
        
var  results  =  [];
        
if  (obj  ==   null return  results;
        
if  (nativeMap  &&  obj.map  ===  nativeMap)  return  obj.map(iterator, context);
        each(obj, 
function  (value, index, list) {
            results[results.length] 
=  iterator.call(context, value, index, list);
        });
        
return  results;
    };

    
//  链式操作主要部分
     var  wrapper  =   function  (obj) {  this ._wrapped  =  obj; };

    _.prototype 
=  wrapper.prototype;

    
//  扩展自定义方法到Wrap包装器上
    _.mixin  =   function  (obj) {
        each(_.functions(obj), 
function  (name) {
            addToWrapper(name, _[name] 
=  obj[name]);
        });
    };
    
    
//  是否对结果进行链式包装返回
     var  result  =   function  (obj, chain) {
        
return  chain  ?  _(obj).chain() : obj;
    };

    
//  将方法扩展到包装器的原型上
     var  addToWrapper  =   function  (name, func) {
        wrapper.prototype[name] 
=   function  () {
            
var  args  =  slice.call(arguments);
            unshift.call(args, 
this ._wrapped);
            
return  result(func.apply(_, args),  this ._chain);
        };
    };

    
//  将所有Underscore上的方法添加到Wrap包装器上
    _.mixin(_);

    
//  扩展Array上的方法到wrap包装器上-包装原数组
    each([ ' pop ' ' push ' ' reverse ' ' shift ' ' sort ' ' splice ' ' unshift ' ],  function  (name) {
        
var  method  =  ArrayProto[name];
        wrapper.prototype[name] 
=   function  () {
            method.apply(
this ._wrapped, arguments);
            
return  result( this ._wrapped,  this ._chain);
        };
    });
    
    
//  扩展Array上的方法到wrap包装器上-包装返回值
    each([ ' concat ' ' join ' ' slice ' ],  function  (name) {
        
var  method  =  ArrayProto[name];
        wrapper.prototype[name] 
=   function  () {
            
return  result(method.apply( this ._wrapped, arguments),  this ._chain);
        };
    });


    
//  添加链式方法的实现
    wrapper.prototype.chain  =   function  () {
        
this ._chain  =   true ;
        
return   this ;
    };

    
//  提取链式包装的内容
    wrapper.prototype.value  =   function  () {
        
return   this ._wrapped;
    };

})();

//  结果测试 步骤:将数组[1,2,3]进行链式包装,然后将其用val * 2来map,紧接着用filter进行val < 5过滤, 
//
 然后pop,concat最后获取其值value
var  re  =  _([ 1 , 2 , 3 ]).chain().map( function  (val) {
    
return  val  *   2 ;
}).filter(
function  (val) {
    
return  val  <   5 ;
}).pop().concat([
' 5 ' ]).value();

alert(re);
< / script>
< / body> 

< /html>


转载于:https://www.cnblogs.com/bluedream2009/archive/2011/07/02/2096309.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值