jasmine214--love

只有当你的内心总是充满快乐、美好的愿望和宁静时,你才能拥有强壮的体魄和明朗、快乐或者宁静的面容。
posts - 731, comments - 60, trackbacks - 0, articles - 0

js--添加自定义的扩展函数--Array 对象

Posted on 2010-06-16 12:12 幻海蓝梦 阅读(1613) 评论(0)  编辑  收藏 所属分类: JS

http://www.cnblogs.com/windows7/archive/2010/05/22/1741612.html
我们经常给 String,Function,Array 的原型加上自定义的扩展函数,比如去除字符串空格,数组排序等

 今天重点讲下 如何给Array对象扩展

1、直接在Array.prototype 上扩展

2、用自己方法对数组对象进行扩展

 

直接在Array.prototype上扩展,不能直接对dom对象使用(如:document.getElementsByTagName('div')得到的nodeList);

对有洁癖的同学而言 也破了原始生态环境的 : )

 

先来看下 yui操作数组的一些方法,这里我对源码简单剥离并改动了下

 

( function (){
    
var  YArray;

    YArray 
=   function (o,idx,arraylike){
        
var  t  =  (arraylike)  ?   2  : YArray.test(o),
         l, a, start 
=  idx  ||   0 ;
          
if  (t) {
            
try  {
                
return  Array.prototype.slice.call(o, start); //借助Array原生方法来把aguments转换为JS数组
            } 
catch (e) {
                a 
=  [];
                l 
=  o.length;
                
for  (; start l; start ++ ) {
                    a.push(o[start]);
                }
                
return  a;
            }
        } 
else  {
            
return  [o];
        }

    }

    YArray.test 
=   function (o){
         
var  r  =   0
        
if  (o  &&  ( typeof  o  ==   ' object '   || typeof  o  ==   ' function ' )) {
              
if  (Object.prototype.toString.call(o)  ===   " [object Array] " ) {
                r 
=   1
            } 
else  {
                
try  {
                    
if  (( ' length '   in  o)  &&   ! o.tagName  &&   ! o.alert  &&   ! o.apply) {
                        r 
=   2 ;
                    }    
                } 
catch (e) {}
            }
        }
        
return  r;
    }

    YArray.each 
=  (Array.prototype.forEach)  ? //先检测浏览器是否已支持,若有则调用原生
        
function  (a, f, o) { 
            Array.prototype.forEach.call(a 
||  [], f, o  ||  Y);
            
return  YArray;
        } :
        
function  (a, f, o) { 
            
var  l  =  (a  &&  a.length)  ||   0 , i;
            
for  (i  =   0 ; i   l; i = i + 1 ) {
                f.call(o 
||  Y, a[i], i, a);
            }
            
return  YArray;
        };

    YArray.hash 
=   function (k, v) {
        
var  o  =  {}, l  =  k.length, vl  =  v  &&  v.length, i;
        
for  (i = 0 ; i l; i = i + 1 ) {
            
if  (k[i]) {
                o[k[i]] 
=  (vl  &&  vl  >  i)  ?  v[i] :  true ;
            }
        }

        
return  o;
    };

    YArray.indexOf 
=  (Array.prototype.indexOf)  ?
        
function (a, val) {
            
return  Array.prototype.indexOf.call(a, val);
        } :
        
function (a, val) {
            
for  ( var  i = 0 ; i a.length; i = i + 1 ) {
                
if  (a[i]  ===  val) {
                    
return  i;
                }
            }
            
return   - 1 ; //寻找不到的情况
        };

    YArray.numericSort 
=   function (a, b) { 
        
return  (a  -  b);   //从小到大排序, return (b - a); 从大到小
    };


    YArray.some 
=  (Array.prototype.some)  ?
        
function  (a, f, o) { 
            
return  Array.prototype.some.call(a, f, o);
        } :
        
function  (a, f, o) {
            
var  l  =  a.length, i;
            
for  (i = 0 ; i l; i = i + 1 ) {
                
if  (f.call(o, a[i], i, a)) {
                    
return   true ;
                }
            }
            
return   false ;
        };

})();

  借助Array原生方法来把aguments转换为JS数组 的其他方法 (Dom对象不可以,只有遍历)

Array.apply( null ,arguments);
[].slice.call(arguments,
0 );
[].splice.call(arguments,
0 ,arguments.length);
[].concat.apply([],arguments);
...


 

 YArray函数不仅可以操作数组对象也对nodeList对象进行了操作

YArray(document.getElementsByTagName( " div " ));

遍历dom对象 重新组装成一个数组 : )

 a  =  [];
  l 
=  o.length;
 
for  (; start l; start ++ ) {
       a.push(o[start]);
   }
 
return  a;


 YArray.each

 遍历数组,如有传入函数,每次遍历都执行callback

YArray.each([ 1 , 2 , 3 ], function (item){
   alert(item);
//  执行了3次,1,2,3
});


YArray.hash

数组 组装成 键值对 可以理解成一个json对象

YArray.hash([ " a " , " b " ],[ 1 , 2 ]); 


 YArray.indexOf

返回(想要找寻值)一样的该值在数组的索引值

 

YArray.indexOf([ 1 , 2 ], 1 )


 YArray.numericSort

对数组进行排序,从小到大

 [ 3 1 2 ].sort(YArray.numericSort);


YArray.some

是否数组中的有元素通过了callBack的处理?如果有,则立马返回true,如果一个都没有,则返回false 

YArray.some([ 3 1 2 ], function (el){
   
return  el    4
})


 

让我们看看 javascript 1.6 -1.8 对数组的扩展 ,并学习如何实现相同的功能

  • every
  • filter
  • forEach
  • indexOf
  • lastIndexOf
  • map
  • some
  • reduce
  • reduceRight

 

				Array.prototype.every
				

 

if  ( ! Array.prototype.every)
{
  Array.prototype.every 
=   function (fun  /* , thisp */ )
  {
    
var  len  =   this .length  >>>   0 ;
    
if  ( typeof  fun  !=   " function " )
      
throw   new  TypeError();

    
var  thisp  =  arguments[ 1 ];
    
for  ( var  i  =   0 ; i   len; i ++ )
    {
      
if  (i  in   this   &&
          
! fun.call(thisp,  this [i], i,  this ))
        
return   false ;
    }

    
return   true ;
  };
}

是否数组中的每个元素都通过了callBack的处理?如果是,则返回true,如果有一个不是,则立马返回false

 这和我们刚才提到的YUI种的 some 函数 很雷同 :) 功能刚好相反

 

 

				Array.prototype.filter

 

Array.prototype.filter  =   function  (block  /* , thisp  */ ) {   // 过滤器 ,添加方便,进行判断过滤
     var  values  =  [];
    
var  thisp  =  arguments[ 1 ];
    
for  ( var  i  =   0 ; i    this .length; i ++ )
        
if  (block.call(thisp,  this [i]))
            values.push(
this [i]);
    
return  values;
};


使用方法

var  val =  numbers.filter( function (t){
    
return  t    5  ;
})
alert(val);


 forEach 和  indexOf 和  some 可以参考 上面yui的代码 ,不再重述

lastIndexOf  和 indexOf  代码相似 只是从最后开始遍历

 

下面讲下 ‘ map’

Array.prototype.map  =   function (fun  /* , thisp */ ) { 
    
var  len  =   this .length  >>>   0 ;
    
if  ( typeof  fun  !=   " function " )
      
throw   new  TypeError();

    
var  res  =   new  Array(len);
    
var  thisp  =  arguments[ 1 ];
    
for  ( var  i  =   0 ; i   len; i ++ ) {
        
if  (i  in   this )
            res[i] 
=  fun.call(thisp,  this [i], i,  this );
    }

    
return  res;
};

遍历数组,执行函数,迭代数组,每个元素作为参数执行callBack方法,由callBack方法对每个元素进行处理,最后返回处理后的一个数组

var numbers = [1, 4, 9];
var roots = numbers.map(function(a){return a * 2});

 

 

				Array.prototype.reduce

 

 Array.prototype.reduce  =   function (fun  /* , initial */ ) { 
    
var  len  =   this .length  >>>   0 ;
    
if  ( typeof  fun  !=   " function " )
        
throw   new  TypeError();

     if  (len  ==   0   &&  arguments.length  ==   1 )
        
throw   new  TypeError();

    
var  i  =   0 ;
    
if  (arguments.length  >=   2 ) {
        
var  rv  =  arguments[ 1 ];
    } 
else  {
        
do  {
            
if  (i  in   this ) {
                rv 
=   this [i ++ ];
                
break ;
            }

             if  ( ++ >=  len)
                
throw   new  TypeError();
        } 
while  ( true );
    }

    
for  (; i   len; i ++ ) {
        
if  (i  in   this )
            rv 
=  fun.call( null , rv,  this [i], i,  this );
    }

    
return  rv;
};

让数组元素依次调用给定函数,最后返回一个值,换言之给定函数一定要用返回值 

 

 

				Array.prototype.reduceRight

 

见名故而思意,从右往左

Array.prototype.reduceRight  =   function (fun  /* , initial */ ) { 
        
var  len  =   this .length  >>>   0 ;
        
if  ( typeof  fun  !=   " function " )
            
throw   new  TypeError();
        
if  (len  ==   0   &&  arguments.length  ==   1 )
            
throw   new  TypeError();

        
var  i  =  len  -   1 ;
        
if  (arguments.length  >=   2 ) {
            
var  rv  =  arguments[ 1 ];
        } 
else  {
            
do  {
                
if  (i  in   this ) {
                    rv 
=   this [i -- ];
                    
break ;
                }
                
if  ( --   0 )
                    
throw   new  TypeError();
            } 
while  ( true );
        }

        
for  (; i  >=   0 ; i -- ) {
            
if  (i  in   this )
                rv 
=  fun.call( null , rv,  this [i], i,  this );
        }
        
return  rv;
    };


除了这些,只用想用到的方法都能加到Array.prototype上

比如常用的toString

Array.prototype.toString  =   function  () {
    
return   this .join( '' ); 
};


还可以添加  toJson ,uniq ,compact,reverse等 

   Array扩展对开发还是很有帮助滴 : ) 


只有注册用户登录后才能发表评论。


网站导航: