最近看到网上很多人在问 JavaScript 里有没有像 PHP 里 array_key_exists
和 in_array
那样的函数。答案当然是“没有”,不过网上给出的大部分解决方案都只是遍历检查。我想说,其实还有更简单的办法。
array_key_exists
在 JavaScript 里实现 array_key_exists
是比较简单的,用 in 运算符:
var obj = {
"Carl": "Old man",
"Russel": "Little boy",
"Kevin": "Giant Snipe",
"Dug": "Golden Retriever"
};
"Kevin" in obj; // true
"Dug" in obj; // true
"Alpha" in obj; // false
不过 in 运算符有个值得注意的问题:它不仅会判断一个对象的属性,还会判断它从 prototype chain 继承的属性。如果在判断时需要排除继承来的属性,你需要改用 Object.hasOwnProperty
方法:
obj.hasOwnProperty("Carl"); // true
obj.hasOwnProperty("hasOwnProperty"); // false
"hasOwnProperty" in obj; // true
可以看到,hasOwnProperty
是继承来的属性,用 Object.hasOwnProperty
方法可以判断出它不是 obj
自己的属性,而 in 运算符则不会注意到这一点。另外,因为在 JavaScript 中,数组是一种特殊的对象,所以 Object.hasOwnProperty
也适用于数组。
BTW,如果你很重视 JavaScript 的性能优化,你就会想到:in 运算符还需要检查对象继承的属性,那么其速度必然较慢。在 Chrome 和 Firefox 上的测试结果表明,事实的确如此。
in_array
在 JavaScript 里实现 in_array
要麻烦一点,因为数组和对象要分开处理。
对于数组,可以用 Array.indexOf
方法:
var arr = ["Carl", "Russel", "Kevin", "Dug"];
arr.indexOf("Russel"); // 1 (返回相应的索引)
arr.indexOf("Beta"); // -1
由于 Array.indexOf
是 JavaScript 1.6 中新增的,对于 IE 8 及以前的版本,需要一个 fallback:
function inArray(needle, haystack) {
if (indexOf in haystack) {
return haystack.indexOf(needle) == -1 ? false : true;
}
var length = haystack.length;
for (var i = 0; i < length; i++) {
if (haystack[i] === needle) return true;
}
return false;
}
至于对象,则只有遍历一途:
function inObject(needle, haystack) {
for (var i in haystack) {
if (haystack.hasOwnProperty(i) && haystack[i] === needle) return true;
}
return false;
}
值得注意的一点:因为用了 for...in
来遍历对象,这同样会遍历到对象继承的属性。所以需要增加 hasOwnProperty
的判断,以确保只在对象自己的属性中寻找。