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
(
++
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
见名故而思意,从右往左
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
(
--
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
Array.prototype.toString
=
function
() {
return
this
.join(
''
);
};
还可以添加 toJson ,uniq ,compact,reverse等
Array扩展对开发还是很有帮助滴 : )