一直以来,遍历对象是个挺麻烦的事,特别是遇到后端那不规范不规则的数据返回的时候,分分钟想掐死……
算了,我F……佛慈悲,自己动手,丰衣足食。
言归正传,和遍历数组不同,object是没有固定下标和顺序可言的,只能通过key值查找,而key值没有一个很完美的方式查找,for in那些总是伴随着兼容问题,新的keys方法也同样如此,那么要很好遍历对象,首先要解决这个问题。
keys的api在ie8等不支持环境会报错,写个hack就好了,具体方法不讨论,可以参考 @di8yuansu 的【关于IE8不支持Object.keys()的处理】
说下思路,不打算在Object原型中拓展,怕冲突,另写个函数就好了。
- 函数接受对象和要遍历查找的key,参数校验后判断类型(数据类型的知识,可以参考我之前的文章:【JavaScript复制对象和数组】);
- 接收到的参数为对象或数组,Object.keys或者数组直接遍历;
- 匹配所有key值,递归遍历查找;
- 最后数组或者undefined返回查找结果
代码实现如下:
/**
* ergod用于遍历对象的值
* @author mo
* @param obj 待遍历对象
* @param key 要遍历的key
* @return 遍历到的值,返回数组集合;如果为空,则返回undefined
* @example
*
var obj = {
a: 2,
e: {
h: [
{ g: 9 }
]
},
f: [
[
{ g: 7 }
]
],
g: {
g: {
g: 6
}
}
}
console.log(ergod(obj, 'g'))
>> [ 9, 7, { g: { g: 6 } }, { g: 6 }, 6 ]
*
*/
;(function() {
var ergod = function(obj, key) {
// 仅接受两个有效参数
if (!obj || obj.constructor !== Object || !key || key.constructor !== String) {
return undefined
}
var oi = 0,
keys = obj.constructor == Object ? Object.keys(obj) : [],
result = [],
tmp
// 数组相关
if (obj.constructor == Array) {
keys = []
for (; oi < obj.length; oi++) {
keys.push(oi)
}
oi = 0
}
for (; oi < keys.length; oi++) {
if (keys[oi] == key) {
result.push(obj[keys[oi]])
}
if (typeof obj[keys[oi]] == 'object') {
tmp = ergod(obj[keys[oi]], key)
}
if (tmp) result = result.concat(tmp)
}
return result.length ? result : undefined
}
// EXPOSE
if (typeof define === "function" && define.amd) {
define(function() { return ergod })
} else if (typeof module !== "undefined" && module.exports) {
module.exports = ergod
} else {
window.ergod = ergod
}
// EXPOSE
})()