检查键是否存在于JavaScript对象中?


2963

如何检查JavaScript对象或数组中是否存在特定键?

如果密钥不存在,而我尝试访问它,它将返回false吗?还是抛出错误?


2
JavaScript中的所有内容(几乎所有内容)都是一个对象,也可以将其强制转换为一个对象。就像@PatrickM指出的那样,这就是伪关联数组的诞生地。
安德鲁·拉尔森

此基准jsben.ch/#/WqlIl为您提供了实现此检查的最常用方法的概述。
EscapeNetscape

一种快速的解决方法,通常我property.key = property.key || 'some default value'
会这样做

Answers:


4112

检查不确定性不是测试密钥是否存在的准确方法。如果键存在但值实际上是undefined怎么办?

var obj = { key: undefined };
obj["key"] !== undefined // false, but the key exists!

您应该改为使用in运算符:

"key" in obj // true, regardless of the actual value

如果要检查键是否不存在,请记住使用括号:

!("key" in obj) // true if "key" doesn't exist in object
!"key" in obj   // ERROR!  Equivalent to "false in obj"

或者,如果您要特别测试对象实例的属性(而不是继承的属性),请使用hasOwnProperty

obj.hasOwnProperty("key") // true

有关和的方法之间的性能比较inhasOwnProperty关键是undefined,请参见此基准


83
手动定义值为undefined的属性绝对没有意义。真的是矛盾。
joebert

259
我坚信在某些情况下,有意将属性设置为undefined。
Ates Goral

168
有效的用例:Gecko 1.9.1 [Firefox 3.5]没有window.onhashchange属性。Gecko 1.9.2 [Firefox 3.6]将此属性设置为undefined(直到哈希更改)。要检测哈希历史记录或浏览器版本,必须使用window.hasOwnProperty(“ onhashchange”);。
SamGoody

7
PHP中存在一个类似的问题,其中null ==不存在:stackoverflow.com/q/418066/372654,不幸的是,null也在那里使用。
HalilÖzgür2012年

80
@joebert只是说些废话并不意味着您不会在生产代码中遇到它。有许多图书馆从事无意义的工作。
Crashworks 2014年

298

快速回答

如何检查JavaScript对象或数组中是否存在特定键?如果密钥不存在,而我尝试访问它,它将返回false吗?还是抛出错误?

使用(关联)数组样式或对象样式直接访问缺少的属性将返回未定义的常量。

缓慢和可靠运营商和hasOwnProperty方法

正如人们在这里已经提到的那样,您可以拥有一个对象,该对象的属性与“未定义”常量关联。

 var bizzareObj = {valid_key:  undefined};

在这种情况下,您将必须使用hasOwnPropertyin运算符来知道密钥是否确实存在。但是,但是价格是多少?

所以,我告诉你...

operator和hasOwnProperty中的in是在Javascript中使用属性描述符机制的“方法”(类似于Java语言中的Java反射)。

http://www.ecma-international.org/ecma-262/5.1/#sec-8.10

“属性描述符”类型用于解释命名属性属性的操纵和确定。属性描述符类型的值是由命名字段组成的记录,其中每个字段的名称都是属性名称,其值是8.6.1中指定的相应属性值。另外,任何字段都可以存在或不存在。

另一方面,调用对象方法或键将使用Javascript [[Get]]机制。那快得多了!

基准

http://jsperf.com/checking-if-a-key-exists-in-a-javascript-array

比较JS中的密钥访问

操作符中 使用
var result = "Impression" in array;

结果是

12,931,832 ±0.21% ops/sec      92% slower 
使用hasOwnProperty
var result = array.hasOwnProperty("Impression")

结果是

16,021,758 ±0.45% ops/sec     91% slower
直接访问元素(括号样式)
var result = array["Impression"] === undefined

结果是

168,270,439 ±0.13 ops/sec     0.02% slower 
直接访问元素(对象样式)
var result = array.Impression  === undefined;

结果是

168,303,172 ±0.20%     fastest

编辑:什么是分配给属性undefined值的原因?

这个问题使我感到困惑。在Javascript中,至少有两个针对不存在的对象的引用,以避免出现此类问题:nullundefined

null是表示有意缺少任何对象值,或者简而言之,就是已确认的缺少值的原始值。另一方面,undefined是未知值(未定义)。如果存在稍后将以适当值使用的属性,请考虑使用null引用,而不是undefined因为在开始时确认该属性缺少值。

相比:

var a = {1: null}; 
console.log(a[1] === undefined); // output: false. I know the value at position 1 of a[] is absent and this was by design, i.e.:  the value is defined. 
console.log(a[0] === undefined); // output: true. I cannot say anything about a[0] value. In this case, the key 0 was not in a[].

劝告

避免使用带有undefined值的对象。尽可能直接检查并用于null初始化属性值。否则,请使用慢速in运算符或hasOwnProperty()方法。

编辑:2018年12月4日-不相关

正如人们所评论的那样,现代版本的Javascript引擎(firefox例外)已经改变了访问属性的方法。对于这种特殊情况,当前的实现比以前的实现要慢,但是访问密钥和对象之间的差异可以忽略不计。


1
所有这些方法都可以在所有常用的浏览器(例如IE8 +)中接受吗?
贾斯汀

11
+1进行基准测试。谢谢,这正是我希望找到的信息。绝对是编写代码的强大参数,该代码从不分配或期望键包含未定义的值。
TJ康普顿

我很好奇Underscore.js的has()是如何比较的,所以我将它添加到了jsperf(版本11)中。原来,它与in和hasOwnProperty()一起位于慢速组中。
mpoisot

3
其中一个原因我会集中未定义的哈希值是,我其实是想删除哈希该财产的关键,但是delete hash[key]比慢得多 hash[key] = undefined。当然,在这种情况下,需要in操作员对我来说没有任何意义,但是它充当了“我们应始终避免将值设置为undefined”的反例。
艾伦·谭

1
正如@HüseyinYağlı提到的那样,如果您检查jsperf链接,则自最初编写此答案以来,大多数浏览器的不同方法之间的性能已发生显着变化。Firefox是使用数组或对象方法仍具有显着优势的少数几个之一,但是对于许多其他浏览器而言,差异是可以忽略的。
kevinmicke '18

144

它将返回undefined

var aa = {hello: "world"};
alert( aa["hello"] );      // popup box with "world"
alert( aa["goodbye"] );    // popup box with "undefined"

undefined是一个特殊的常数值。所以你可以说,例如

// note the three equal signs so that null won't be equal to undefined
if( aa["goodbye"] === undefined ) {
    // do something
}

这可能是检查丢失键的最佳方法。但是,正如下面的评论中指出的那样,从理论上讲,您可能希望将实际值设为undefined。我从来不需要这样做,也无法想出我为什么要使用的临时原因,但是为了完整起见,您可以使用in运算符

// this works even if you have {"goodbye": undefined}
if( "goodbye" in aa ) {
    // do something
}

8
如果键存在但值实际上未定义怎么办?
Ates Goral

13
与未定义比较时,应使用===而不是==,否则null将等于未定义。
马修·克鲁姆利

10
以利您的答案并不完全准确。因为无论如何(当然不应该这样做),undefined不是一个特殊的常数。实际上,它不是保留关键字,您可以覆盖它,例如,that var undefined = 42;。测试未定义的道具时,应始终使用((typeof variable) === "undefined")
ssice 2011年


1
在JavaScript的早期版本中,“ undefined”和“ NaN”是可变变量,可以重新定义或分配其他值。这是一件坏事。这5固定在ECMAScript中
jkdev


29
"key" in obj

可能只测试与数组键非常不同的对象属性值


对于在类原型上定义的键,此代码也将为true:函数A(){}; A.prototype.b = 2; var a = new A(); 那么a中的“ b”为真。虽然a.hasOwnProperty('b')当然是错误的。
亚历山大

24

检查javascript对象中是否存在属性的三种方法:

  1. !! obj.theProperty
    将值转换为bool。对于除“ false”值以外的所有值,返回TRUE
  2. obj中的'theProperty'
    如果属性存在,则无论其值如何(即使为空)也将返回true
  3. obj.hasOwnProperty('theProperty')
    不检查原型链。(由于所有对象都具有'toString'方法,因此1和2将对其返回true,而3可对其返回false。)

参考:

http://book.mixu.net/node/ch5.html


!! obj.theProperty在值未定义时失败。例如:var a = {a : undefined, b : null}; !!a.a **will return false**
ARJUN

15

如果您使用的是underscore.js库,则对象/数组操作将变得简单。

在您的情况下,可以使用_.has方法。例:

yourArray = {age: "10"}

_.has(yourArray, "age")

返回true

但,

_.has(yourArray, "invalidKey")

返回


15

回答:

if ("key" in myObj)
{
    console.log("key exists!");
}
else
{
    console.log("key doesn't exist!");
}

说明:

in运营商将检查关键的对象存在。如果检查该值是否未定义:if (myObj["key"] === 'undefined'),则可能会遇到问题,因为带有该undefined值的对象中可能存在一个键。

因此,更好的做法是先使用in运算符,然后在知道密钥存在后再比较该密钥内部的值。


12

这是一个我发现非常有用的辅助函数

keyExists(key, search)可以用来轻松地在对象或数组中查找键!

只需将要查找的键传递给它,然后搜索要在其中查找的obj(对象或数组)。

function keyExists(key, search) {
        if (!search || (search.constructor !== Array && search.constructor !== Object)) {
            return false;
        }
        for (var i = 0; i < search.length; i++) {
            if (search[i] === key) {
                return true;
            }
        }
        return key in search;
    }

// How to use it:
// Searching for keys in Arrays
console.log(keyExists('apple', ['apple', 'banana', 'orange'])); // true
console.log(keyExists('fruit', ['apple', 'banana', 'orange'])); // false

// Searching for keys in Objects
console.log(keyExists('age', {'name': 'Bill', 'age': 29 })); // true
console.log(keyExists('title', {'name': 'Jason', 'age': 29 })); // false

它已经相当可靠,并且可以跨浏览器很好地工作。


6
这似乎有些混乱:首先,在搜索数组时,此方法正在检查,而不是键。其次,当您可以使用内置Array.indexOf方法时,为什么要遍历这样的数组?(如果您正在寻找一个值,那就是)
Nick F

9

香草js

yourObjName.hasOwnProperty(key) : true ? false;

如果要检查对象在es2015中是否至少具有一个属性

Object.keys(yourObjName).length : true ? false

7

ES6解决方案

使用Array#someObject.keys。如果给定密钥存在于对象中,则返回true;否则,返回false

var obj = {foo: 'one', bar: 'two'};
    
function isKeyInObject(obj, key) {
    var res = Object.keys(obj).some(v => v == key);
    console.log(res);
}

isKeyInObject(obj, 'foo');
isKeyInObject(obj, 'something');

单行示例。

console.log(Object.keys({foo: 'one', bar: 'two'}).some(v => v == 'foo'));


1
对于对象的无数属性,它将失败。
Sid

@Sid给我举个例子。
亲切的用户,

干得好。let joshua = {名称:“ Joshua”,地址:“伦敦”};Object.defineProperty(joshua,'isMarried',{值:true,可枚举:false});console.log('Object.keys(joshua)中的'isMarried')
Sid

我正在将您的解决方案应用于我的对象。它不应该对第一次输出是正确的吗?console.log(Object.keys(joshua).some(v => v =='isMarried')); console.log(joshua.isMarried);
2017年

1
抱歉,您是否检查了第二个控制台语句的输出?Object.defineProperty等效于使用点表示法设置属性。
2017年

6

我们可以用 - hasOwnProperty.call(obj, key);

underscore.js方式-

if(_.has(this.options, 'login')){
  //key 'login' exists in this.options 
}

_.has = function(obj, key) {
  return hasOwnProperty.call(obj, key);
};

5

最简单的检查方法是

"key" in object

例如:

var obj = {
  a: 1,
  b: 2,
}
"a" in obj // true
"c" in obj // false

返回值为true表示键存在于对象中。


4

对于那些lodash包含在他们的项目中的对象:
有一个lodash的_.get方法,它试图获取“深”键:

获取对象路径处的值。如果解析的值未定义,则将在其位置返回defaultValue。

var object = { 'a': [{ 'b': { 'c': 3 } }] };

console.log(
  _.get(object, 'a[0].b.c'),           // => 3
  _.get(object, ['a', '0', 'b', 'c']), // => 3
  _.get(object, 'a.b.c'),              // => undefined 
  _.get(object, 'a.b.c', 'default')    // => 'default'
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>


这将有效地检查该键(无论深度如何)是否已定义,并且如果未定义该键,则不会引发可能会损害程序流程的错误。


4

虽然这不一定检查键是否存在,但是会检查值的真实性。这undefinednull在秋天。

Boolean(obj.foo)

此解决方案最适合我,因为我使用打字稿,并使用像这样的字符串'foo' in objobj.hasOwnProperty('foo') 检查键是否存在不会为我提供智能感知。


3

如果要检查对象上任何深度的任何键并考虑虚假值,请考虑将以下行用于实用程序功能:

var keyExistsOn = (o, k) => k.split(".").reduce((a, c) => a.hasOwnProperty(c) ? a[c] || 1 : false, Object.assign({}, o)) === false ? false : true;

结果

var obj = {
    test: "",
    locals: {
        test: "",
        test2: false,
        test3: NaN,
        test4: 0,
        test5: undefined,
        auth: {
            user: "hw"
        }
    }
}

keyExistsOn(obj, "")
> false
keyExistsOn(obj, "locals.test")
> true
keyExistsOn(obj, "locals.test2")
> true
keyExistsOn(obj, "locals.test3")
> true
keyExistsOn(obj, "locals.test4")
> true
keyExistsOn(obj, "locals.test5")
> true
keyExistsOn(obj, "sdsdf")
false
keyExistsOn(obj, "sdsdf.rtsd")
false
keyExistsOn(obj, "sdsdf.234d")
false
keyExistsOn(obj, "2134.sdsdf.234d")
false
keyExistsOn(obj, "locals")
true
keyExistsOn(obj, "locals.")
false
keyExistsOn(obj, "locals.auth")
true
keyExistsOn(obj, "locals.autht")
false
keyExistsOn(obj, "locals.auth.")
false
keyExistsOn(obj, "locals.auth.user")
true
keyExistsOn(obj, "locals.auth.userr")
false
keyExistsOn(obj, "locals.auth.user.")
false
keyExistsOn(obj, "locals.auth.user")
true

另请参阅以下NPM软件包:https : //www.npmjs.com/package/has-deep-value


3
const object1 = {
  a: 'something',
  b: 'something',
  c: 'something'
};

const key = 's';

// Object.keys(object1) will return array of the object keys ['a', 'b', 'c']

Object.keys(object1).indexOf(key) === -1 ? 'the key is not there' : 'yep the key is exist';

3

在“数组”世界中,我们可以将索引视为某种键。令人惊讶的是,in运算符(对象的最佳选择)也可用于数组。不存在的键的返回值是undefined

let arr = ["a","b","c"]; // we have indexes: 0,1,2
delete arr[1];           // set 'empty' at index 1
arr.pop();               // remove last item

console.log(0 in arr,  arr[0]);
console.log(1 in arr,  arr[1]);
console.log(2 in arr,  arr[2]);


2

yourArray.indexOf(yourArrayKeyName)> -1

fruit = ['apple', 'grapes', 'banana']

fruit.indexOf('apple') > -1

真正


fruit = ['apple', 'grapes', 'banana']

fruit.indexOf('apple1') > -1


0

这些示例可以证明不同方法之间的差异。希望它将帮助您选择适合您的需求的产品:

// Lets create object `a` using create function `A`
function A(){};
A.prototype.onProtDef=2;
A.prototype.onProtUndef=undefined;
var a=new A();
a.ownProp = 3;
a.ownPropUndef = undefined;

// Let's try different methods:

a.onProtDef; // 2
a.onProtUndef; // undefined
a.ownProp; // 3
a.ownPropUndef; // undefined
a.whatEver; // undefined
a.valueOf; // ƒ valueOf() { [native code] }

a.hasOwnProperty('onProtDef'); // false
a.hasOwnProperty('onProtUndef'); // false
a.hasOwnProperty('ownProp'); // true
a.hasOwnProperty('ownPropUndef'); // true
a.hasOwnProperty('whatEver'); // false
a.hasOwnProperty('valueOf'); // false

'onProtDef' in a; // true
'onProtUndef' in a; // true
'ownProp' in a; // true
'ownPropUndef' in a; // true
'whatEver' in a; // false
'valueOf' in a; // true (on the prototype chain - Object.valueOf)

Object.keys(a); // ["ownProp", "ownPropUndef"]

-1

全新的JavaScript解构解决方案:

let obj = {
    "key1": "value1",
    "key2": "value2",
    "key3": "value3",
};

let {key1, key2, key3, key4} = obj;

// key1 = "value1"
// key2 = "value2"
// key3 = "value3"
// key4 = undefined

// Can easily use `if` here on key4
if(!key4) { console.log("key not present"); } // Key not present

检查其他使用JavaScript的方法

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.