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操作數組的一些方法,這里我對源碼簡單剝離并改動了下
?
???? 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對象不可以,只有遍歷)
[].slice.call(arguments, 0 );
[].splice.call(arguments, 0 ,arguments.length);
[].concat.apply([],arguments);
...
?
?YArray函數不僅可以操作數組對象也對nodeList對象進行了操作
遍歷dom對象 重新組裝成一個數組 : )
? l? = ?o.length;
? for ?(;?start l;?start ++ )?{
?????? a.push(o[start]);
?? }
? return ?a;
?YArray.each
?遍歷數組,如有傳入函數,每次遍歷都執行callback
???alert(item); // ?執行了3次,1,2,3
});
YArray.hash
數組 組裝成 鍵值對 可以理解成一個json對象
?YArray.indexOf
返回(想要找尋值)一樣的該值在數組的索引值
?
?YArray.numericSort
對數組進行排序,從小到大
YArray.some
是否數組中的有元素通過了callBack的處理?如果有,則立馬返回true,如果一個都沒有,則返回false?
??? return ?el? ? 4 ;?
})
?
- every
- filter
- forEach
- indexOf
- lastIndexOf
- map
- some
-
reduce
-
reduceRight
?
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
?
???? 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;
};
使用方法
???? return ?t? ? 5 ?;
})
alert(val);
?forEach 和 ?indexOf 和 ?some 可以參考 上面yui的代碼 ,不再重述
lastIndexOf? 和 indexOf? 代碼相似 只是從最后開始遍歷
?
下面講下 ‘ map’
???? 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
?
???? 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 ?( ++ i? >= ?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
?
見名故而思意,從右往左
???????? 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 ?( -- i? ? 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
???? return ? this .join( '' );?
};
還可以添加? toJson ,uniq ,compact,reverse等?
?? Array擴展對開發還是很有幫助滴 : )?