题 检查JavaScript对象中是否存在密钥?


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

如果某个密钥不存在,并且我尝试访问它,它会返回false吗?或者抛出错误?


2228
2017-07-08 13:21


起源


JavaScript中的所有内容(几乎所有内容)都是一个Object,或者可以作为一个对象进行转换。这就是伪关联数组诞生的地方,就像@PatrickM指出的那样。 - Andrew Larsson
这个基准 jsben.ch/#/WqlIl 为您提供有关如何实现此检查的最常用方法的概述。 - EscapeNetscape


答案:


检查undefined-ness不是测试密钥是否存在的准确方法。如果密钥存在但值实际上该怎么办? 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,看到这个 基准


3087
2017-07-08 15:51



拥有一个手动定义的undefined值的属性绝对没有意义。这真的是矛盾的。 - joebert
我确信有一些用例可以将属性设置为未定义。 - Ates Goral
有效用例:Gecko 1.9.1 [Firefox 3.5]没有window.onhashchange属性。 Gecko 1.9.2 [Firefox 3.6]将此属性设置为undefined(直到哈希更改)。要检测哈希历史记录或浏览器版本,必须使用window.hasOwnProperty(“onhashchange”); - SamGoody
PHP中存在类似的问题,其中null ==不存在: stackoverflow.com/q/418066/372654 不幸的是,null也有用处。 - Halil Özgür
@joebert只是因为某些东西是胡说八道并不意味着你不会在生产代码中遇到它。有许多图书馆做无意义的事情。 - Crashworks


快速回答

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

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

慢而可靠  操作员和 hasOwnProperty 方法

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

 var bizzareObj = {valid_key:  undefined};

在这种情况下,你将不得不使用 hasOwnProperty 要么  操作员知道钥匙是否真的存在。但, 但是以什么价格?

所以,我告诉你......

 操作员和 hasOwnProperty 是在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

Comparing key access in 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中,至少有两个对缺席对象的引用,以避免这样的问题: null 和 undefined

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() 方法。

编辑:12/04/2018 - 不相关任何人

正如人们所评论的那样,现代版本的Javascript引擎(使用firefox异常)改变了访问属性的方法。对于这种特定情况,当前实现比前一个实现慢,但是访问密钥和对象之间的差异是可忽略的。


224
2018-02-27 16:38



所有这些方法都可以在所有常用浏览器中使用,例如IE8 +? - Justin
@Justin是的。它应该工作。你可以直接测试 jsperf.com/checking-if-a-key-exists-in-a-javascript-array。 - rdllopes
+1用于基准测试。谢谢,这正是我希望找到的信息。绝对是编写代码的强有力的论据,这些代码永远不会分配或期望密钥包含该值 未定义。 - T.J. Compton
我将undefined设置为哈希值的一个原因是我实际上想从哈希中删除该属性键,但是 delete hash[key] 是 慢得多  hash[key] = undefined。当然在这种情况下我不需要它 in 运算符,但它作为“我们应该总是避免将值设置为未定义”的反例。 - Alan Tam
正如@HüseyinYağlı所提到的,如果你检查一下 jsperf 链接,自从这个答案最初编写以来,大多数浏览器的不同方法之间的性能发生了显着变化。 Firefox是使用数组或对象方法仍然具有显着优势的少数几个之一,但对于许多其他浏览器而言,差异可以忽略不计。 - kevinmicke


它会回来 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
}

114
2017-07-08 13:24



如果密钥存在但值实际上未定义怎么办? - Ates Goral
在与undefined进行比较时,您应该使用===而不是==,否则null将比较等于undefined。 - Matthew Crumley
Eli你的答案并不完全准确。因为无论如何(当然不应该这样做)undefined不是一个特殊的常量值。事实上,它不是一个保留的关键字,你可以覆盖它,例如,比方说 var undefined = 42;。在测试未定义的道具时,您应该始终使用 ((typeof variable) === "undefined")。 - ssice
@ssice undefined 根据规范,它不是可写的财产 ecma-international.org/ecma-262/5.1/#sec-15.1.1.3 - therealrootuser
在早期版本的JavaScript中,'undefined'和'NaN'是可变变量 可以重新定义或分配其他值。这是件坏事。它已在ECMAScript 5中修复。 - jkdev


接受了答案 是指 目的。小心使用 in 操作者 上 排列 查找数据而不是键:

("true" in ["true", "false"])
// -> false (Because the keys of the above Array are actually 0 and 1)

要测试数组中的现有元素: 查找项目是否在JavaScript数组中的最佳方法?


22
2017-07-01 12:45





"key" in obj

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


20
2018-04-25 15:45



对于在类原型上定义的键,此代码也将成立:函数A(){}; A.prototype.b = 2; var a = new A();然后'a'中的'b'是真的。虽然a.hasOwnProperty('b')当然是假的。 - Alexander


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

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

参考:

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


20
2017-11-12 09:19





如果你正在使用 underscore.js 库然后对象/数组操作变得简单。

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

yourArray = {age: "10"}

_.has(yourArray, "age")

回报 真正 

但,

_.has(yourArray, "invalidKey")

回报


13
2018-05-29 19:37





回答:

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

说明:

in operator将检查对象中是否存在密钥。如果您检查了值是否未定义: if (myObj["key"] === 'undefined'),你可能会遇到问题,因为你的对象中可能存在一个键 undefined 值。

出于这个原因,首先使用它是更好的做法 in 运算符然后在您知道密钥存在之后比较密钥内的值。


10
2018-06-22 02:29





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

这个 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;
}

如何使用它:

在数组中搜索键

keyExists('apple', ['apple', 'banana', 'orange']); // true
keyExists('fruit', ['apple', 'banana', 'orange']); // false

在对象中搜索键

keyExists('age', {'name': 'Bill', 'age': 29 }); // true
keyExists('title', {'name': 'Jason', 'age': 29 }); // false

它非常可靠,并且跨浏览器运行良好。


9
2018-03-05 12:56



这看起来有点混乱:首先,在搜索数组时,这个方法正在检查a 值,而不是一把钥匙。其次,当你可以使用内置时,为什么要迭代这样的数组 Array.indexOf 方法? (如果你正在寻找一个值,那就是) - Nick F