|
我们经常给 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扩展对开发还是很有帮助滴 : ) |
|