繁体   English   中英

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

[英]Checking if a key exists in a JavaScript object?

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

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

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

基准测试结果

快速回答

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

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

慢而可靠运营商和hasOwnProperty方法

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

 var bizzareObj = {valid_key:  undefined};

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

所以,我告诉你...

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

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

属性描述符类型用于解释命名属性属性的操作和具体化。 Property Descriptor 类型的值是由命名字段组成的记录,其中每个字段的名称是一个属性名称,其值是 8.6.1 中指定的相应属性值。 此外,任何字段都可以存在或不存在。

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

基准

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

比较 JS 中的密钥访问 .

运算符中使用
var result = "Impression" in array;

结果是

var result = array.hasOwnProperty("Impression")
使用 hasOwnProperty
var result = array["Impression"] === undefined

结果是

168,270,439 ±0.13 ops/sec     0.02% slower 
直接访问元素(括号样式)
168,303,172 ±0.20%     fastest

结果是

168,270,439 ±0.13 ops/sec 0.02% slower
直接访问元素(对象样式)
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[].

结果是

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, ie: 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 例外)已经改变了访问属性的方法。 对于这种特殊情况,当前的实现比前一个慢,但访问密钥和对象之间的差异可以忽略不计。

它将返回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
}
"key" in obj

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

接受的答案是指Object 当心在Array上使用in运算符来查找数据而不是键:

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

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

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

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

参考:

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

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

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

yourArray = {age: "10"}

_.has(yourArray, "age")

返回

但,

_.has(yourArray, "invalidKey")

返回

回答:

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

解释:

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

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

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

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

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

香草js

yourObjName.hasOwnProperty(key) : true ? false;

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

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

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'));

可选链操作符

 const invoice = {customer: {address: {city: "foo"}}} console.log( invoice?.customer?.address?.city ) console.log( invoice?.customer?.address?.street ) console.log( invoice?.xyz?.address?.city )

查看支持的浏览器列表


对于那些在他们的项目中包含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, 'abc'), // => undefined _.get(object, 'abc', 'default') // => 'default' )
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>


这将有效地检查该键是否已定义,无论该键有多,并且如果未定义该键,则不会抛出可能会损害程序流程的错误。

最简单的检查方法是

"key" in object

例如:

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

返回值为true意味着该对象中存在键。

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

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

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

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

Boolean(obj.foo)

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

Optional Chaining ( ?. ) 运算符也可以用于此

来源: MDN/Operators/Optional_chaining

 const adventurer = { name: 'Alice', cat: { name: 'Dinah' } } console.log(adventurer.dog?.name) // undefined console.log(adventurer.cat?.name) // Dinah

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';

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

yourArray.indexOf(yourArrayKeyName) > -1

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

fruit.indexOf('apple') > -1

真的


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

fruit.indexOf('apple1') > -1

错误的

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

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

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

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

请参见结合空合并运算符

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

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

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

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

 const hasKey = 'FinancialRiskIntent' in data.meta.prediction.intents; if(hasKey) { console.log('The key exists.'); } else { console.log('The key does not exist.'); }

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

希望这对某人有所帮助。

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()使用此方法,因为它也适用于使用Object.create(null)创建的对象以及覆盖继承的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

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

根据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()比接受的答案中提到的其他方法慢(根据我的基准测试)。 但是,如果您只在代码中使用它几次,我认为这种方法不会有太多问题。

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

要查找对象中是否存在键,请使用

Object.keys(obj).includes(key)

ES7 包含检查 Array 是否包含项目的方法, & 是indexOf的更简单替代方法。

新的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 解构的其他用途

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM