检查 JavaScript 对象中是不是存在键?

Posted

技术标签:

【中文标题】检查 JavaScript 对象中是不是存在键?【英文标题】:Checking if a key exists in a JavaScript object?检查 JavaScript 对象中是否存在键? 【发布时间】:2010-11-09 01:00:12 【问题描述】:

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

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

【问题讨论】:

JavaScript 中的所有东西(几乎所有东西)都是一个对象,或者可以转换为一个对象。就像@PatrickM 指出的那样,这就是伪关联数组诞生的地方。 此基准jsben.ch/#/WqlIl 为您概述了如何实现此检查的最常见方法。 一个快速的解决方法,通常我会选择property.key = property.key || 'some default value',以防万一我希望该密钥存在并具有一定的价值 【参考方案1】:

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

var obj =  key: undefined ;
console.log(obj["key"] !== undefined); // false, but the key exists!

您应该改用in 运算符:

var obj =  key: undefined ;
console.log("key" in obj); // true, regardless of the actual value

如果要检查某个键是否不存在,记得使用括号:

var obj =  not_key: undefined ;
console.log(!("key" in obj)); // true if "key" doesn't exist in object
console.log(!"key" in obj);   // Do not do this! It is equivalent to "false in obj"

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

var obj =  key: undefined ;
console.log(obj.hasOwnProperty("key")); // true

inhasOwnProperty 和 key 为 undefined 的方法之间的性能比较,请参阅this benchmark

【讨论】:

我确信存在有意将属性设置为未定义的用例。 有效用例:Gecko 1.9.1 [Firefox 3.5] 没有 window.onhashchange 属性。 Gecko 1.9.2 [Firefox 3.6] 将此属性设置为未定义(直到哈希更改)。要检测哈希历史或浏览器版本,必须使用 window.hasOwnProperty("onhashchange"); 随机事实:设置为undefined 的属性不会被JSON.stringify(...) 序列化,而null 会。因此,任何设置为undefined 且往返于 JSON 的东西都会消失。您还可以使用delete obj.propName 来删除对象的属性。【参考方案2】:

快速解答

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

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

缓慢而可靠的in算子和hasOwnProperty方法

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

 var bizzareObj = valid_key:  undefined;

在这种情况下,您将不得不使用 hasOwnPropertyin 运算符来了解密钥是否真的存在。但是,但价格是多少?

所以,我告诉你...

in 运算符和 hasOwnProperty 是在 Javascript 中使用 Property Descriptor 机制的“方法”(类似于 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

.

使用 in 运算符
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 是一个未知值(未定义)。如果有一个属性将在以后使用 proper 值,请考虑使用 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 例外)已经改变了访问属性的方法。对于这种特殊情况,当前的实现比以前的实现要慢,但访问键和对象之间的差异可以忽略不计。

【讨论】:

【参考方案3】:

它将返回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

【讨论】:

是的。无论是创建为对象还是数组,它都返回 undefined。 如果键存在但值实际上未定义怎么办? 与 undefined 比较时应使用 === 而不是 ==,否则 null 将与 undefined 比较。【参考方案4】:
"key" in obj

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

【讨论】:

【参考方案5】:

accepted answer 指的是Object。当心使用Array 上的in operator 来查找数据而不是键:

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

要测试 Array 中的现有元素:Best way to find if an item is in a JavaScript array?

【讨论】:

【参考方案6】:

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

    !!obj.theProperty 将值转换为布尔值。为除false 值之外的所有值返回true 'theProperty' 在 obj 中 如果属性存在,则返回 true,无论其值如何(甚至为空) 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** 来自评论:!!obj.theProperty 不是检查对象是否具有名为 theProperty 的属性的解决方案。对于任何虚假的属性值,undefined、null、数字0NaN,以及空字符串"",它都会失败【参考方案7】:

如果您使用underscore.js 库,那么对象/数组操作变得简单。

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

yourArray = age: "10"

_.has(yourArray, "age")

返回

但是,

_.has(yourArray, "invalidKey")

返回 false

【讨论】:

【参考方案8】:

答案:

if ("key" in myObj)

    console.log("key exists!");

else

    console.log("key doesn't exist!");

说明:

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

出于这个原因,最好先使用in 运算符,然后在您知道它存在后比较键中的值。

【讨论】:

【参考方案9】:

这是一个我觉得非常有用的辅助函数

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

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

【讨论】:

这似乎有点混乱:首先,当搜索一个数组时,这个方法是检查一个,而不是一个键。其次,既然可以使用内置的Array.indexOf 方法,为什么还要遍历这样的数组呢? (如果你正在寻找一个价值,那就是)【参考方案10】:

香草js

yourObjName.hasOwnProperty(key) : true ? false;

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

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

【讨论】:

【参考方案11】:

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 =&gt; v == 'foo'));

【讨论】:

对象的不可数属性会失败。 @Sid 举个例子。 给你。让约书亚= 名称:'约书亚',地址:'伦敦'; Object.defineProperty(joshua, 'isMarried', value: true, enumerable: false); console.log('isMarried' in Object.keys(joshua)) 我正在将您的解决方案应用于我的对象。第一个输出不应该是真的吗? console.log(Object.keys(joshua).some(v => v == 'isMarried')); console.log(joshua.isMarried); 很抱歉,您检查了第二个控制台语句的输出吗? Object.defineProperty 相当于使用点表示法设置属性。【参考方案12】:

Optional chaining operator:

const invoice = customer: address: city: "foo"

console.log( invoice?.customer?.address?.city )
console.log( invoice?.customer?.address?.street )
console.log( invoice?.xyz?.address?.city )

See supported browsers list


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

获取对象路径的值。如果解析的值未定义, 默认值在其位置返回。

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'
)
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"&gt;&lt;/script&gt;

这将有效地检查是否定义了该键,但 deep,如果未定义该键,不会抛出可能损害程序流程的错误.

【讨论】:

【参考方案13】:

最简单的检查方法是

"key" in object

例如:

var obj = 
  a: 1,
  b: 2,

"a" in obj // true
"c" in obj // false

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

【讨论】:

【参考方案14】:

可选链接 (?.) 运算符也可用于此

来源:MDN/Operators/Optional_chaining

const adventurer = 
  name: 'Alice',
  cat: 
    name: 'Dinah'
  


console.log(adventurer.dog?.name) // undefined
console.log(adventurer.cat?.name) // Dinah

【讨论】:

【参考方案15】:

我们可以使用-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);
;

【讨论】:

【参考方案16】:

如果您想检查对象上任何深度的任何键并考虑错误值,请考虑使用此行作为实用函数:

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

【讨论】:

【参考方案17】:

虽然这不一定会检查键是否存在,但它会检查值的真实性。 undefinednull 属于哪个。

Boolean(obj.foo)

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

【讨论】:

【参考方案18】:
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';

【讨论】:

【参考方案19】:

在“数组”世界中,我们可以将索引视为某种键。令人惊讶的是 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]);

【讨论】:

【参考方案20】:

yourArray.indexOf(yourArrayKeyName) > -1

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

fruit.indexOf('apple') > -1


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

fruit.indexOf('apple1') > -1

【讨论】:

【参考方案21】:

值得注意的是,自从 ES11 引入以来,您可以使用 nullish coalescing 运算符,这大大简化了事情:

const obj = foo: 'one', bar: 'two';

const result = obj.foo ?? "Not found";

对于 foo 中的任何“虚假”值,上面的代码将返回“未找到”。否则它将返回 obj.foo。

见Combining with the nullish coalescing operator

【讨论】:

【参考方案22】:

另一种使用“反射”的方法

根据MDN

Reflect 是一个内置对象,它提供了可拦截的方法 JavaScript 操作。

静态 Reflect.has() 方法的工作方式类似于 in 运算符 功能。

var obj = 
  a: undefined,
  b: 1,
  c: "hello world"

console.log(Reflect.has(obj, 'a'))
console.log(Reflect.has(obj, 'b'))
console.log(Reflect.has(obj, 'c'))
console.log(Reflect.has(obj, 'd'))

我应该使用它吗?

视情况而定。

Reflect.has() 比接受答案中提到的其他方法慢(根据我的基准测试)。但是,如果您只在代码中使用它几次,我看不出这种方法有什么问题。

【讨论】:

【参考方案23】:

这些例子可以展示不同方式之间的差异。希望它能帮助您选择适合您需求的产品:

// 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"]

【讨论】:

【参考方案24】:

就我而言,我想检查 LUIS 返回的 NLP 元数据,它是一个对象。我想检查作为字符串“FinancialRiskIntent”的键是否作为该元数据对象中的键存在。

    我试图定位我需要检查的嵌套对象 -> data.meta.prediction.intents(仅出于我自己的目的,您可以是任何对象) 我使用下面的代码来检查密钥是否存在:

const hasKey = 'FinancialRiskIntent' in data.meta.prediction.intents;

if(hasKey) 
  console.log('The key exists.');

else 
  console.log('The key does not exist.');

这是检查我最初寻找的特定密钥。

希望这一点对某人有所帮助。

【讨论】:

【参考方案25】:

2021 - 使用新方法 Object.hasOwn() 替代 Object.hasOwnProperty()

Object.hasOwn() 旨在替代Object.hasOwnProperty(),是一种可供使用的新方法(但尚未得到所有浏览器(如 safari)的完全支持,但很快就会支持)

Object.hasOwn() 是一个静态方法,如果指定对象具有指定属性作为其自己的属性,则返回 true。如果该属性是继承的,或者不存在,则该方法返回 false。

const person =  name: 'dan' ;

console.log(Object.hasOwn(person, 'name'));// true
console.log(Object.hasOwn(person, 'age'));// false

const person2 = Object.create(gender: 'male');

console.log(Object.hasOwn(person2, 'gender'));// false

在 Object.prototype.hasOwnProperty() 上使用它的动机是什么? - 建议在 Object.hasOwnProperty() 上使用此方法,因为它也适用于使用 @987654330 创建的对象@ 和覆盖了继承的 hasOwnProperty() 方法的对象。虽然可以通过在外部对象上调用 Object.prototype.hasOwnProperty() 来解决这类问题,但 Object.hasOwn() 克服了这些问题,因此是首选(参见下面的示例)

let person = 
  hasOwnProperty: function() 
    return false;
  ,
  age: 35
;

if (Object.hasOwn(person, 'age')) 
  console.log(person.age); // true - the remplementation of hasOwnProperty() did not affect the Object

let person = Object.create(null);
person.age = 35;
if (Object.hasOwn(person, 'age')) 
  console.log(person.age); // true - works regardless of how the object was created

更多关于Object.hasOwn的信息可以在这里找到:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn

浏览器兼容性 - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn#browser_compatibility

【讨论】:

【参考方案26】:

JS 双感叹号!! 符号在这种情况下可能会有所帮助。

const cars = 
        petrol:
            price: 5000
        ,
        gas:
            price:8000
        
    

假设我们有上面的对象,如果你尝试用汽油价格记录汽车。

=> console.log(cars.petrol.price);
=> 5000

您肯定会从中获得 5000 分。但是如果你试图获得一个 不存在的电动车你会得到undefine

=> console.log(cars.electric);
=> undefine

但是使用 !! 这是将变量转换为 布尔值(真或假)。

=> console.log(!!cars.electric);
=> false

【讨论】:

【参考方案27】:

使用 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

请检查other use of JavaScript Destructuring

【讨论】:

【参考方案28】:

一个快速简单的解决方案是将您的对象转换为 json,然后您就可以完成这项简单的任务:

const allowed = 
    '/login' : '',
    '/register': '',
    '/resetpsw': ''
;
console.log('/login' in allowed); //returns true

如果您使用数组,对象键将被转换为整数,例如 0、1、2、3 等。因此,它将始终为 false

【讨论】:

以上是关于检查 JavaScript 对象中是不是存在键?的主要内容,如果未能解决你的问题,请参考以下文章

测试嵌套 JavaScript 对象键是不是存在

测试嵌套 JavaScript 对象键是不是存在

检查对象中是不是存在键[重复]

检查Javascript中对象数组中的键是不是?

检查对象数组中是不是存在具有特定键值的对象

javascript 检查嵌套对象键的存在