检查JavaScript对象中键是否存在的方法
技术背景
在JavaScript开发中,经常需要检查一个对象中是否存在某个特定的键。这看似简单,但当键对应的值为undefined
时,简单的检查值是否为undefined
就会出现问题。因此,需要掌握多种准确检查键是否存在的方法。
实现步骤
1. 使用in
操作符
in
操作符可以检查一个键是否存在于对象中,无论该键对应的值是什么。
1 2
| var obj = { key: undefined }; console.log("key" in obj);
|
如果要检查键不存在的情况,记得使用括号:
1 2 3
| var obj = { not_key: undefined }; console.log(!("key" in obj)); console.log(!"key" in obj);
|
2. 使用hasOwnProperty
方法
如果只想检查对象实例自身的属性(而不是继承的属性),可以使用hasOwnProperty
方法。
1 2
| var obj = { key: undefined }; console.log(obj.hasOwnProperty("key"));
|
3. 使用Object.hasOwn()
方法
Object.hasOwn()
是Object.hasOwnProperty()
的替代方法,它也用于检查对象自身的属性。
1 2 3 4 5 6
| const person = { name: 'dan' }; console.log(Object.hasOwn(person, 'name')); console.log(Object.hasOwn(person, 'age'));
const person2 = Object.create({gender: 'male'}); console.log(Object.hasOwn(person2, 'gender'));
|
4. 使用Object.keys().includes()
方法
可以使用Object.keys()
获取对象的所有键,然后使用includes()
方法检查指定的键是否存在。
1 2 3 4
| const obj = { name: 'John', age: 30 }; const key = 'name'; const keyExists = Object.keys(obj).includes(key); console.log(keyExists);
|
5. 使用Reflect.has()
方法
Reflect.has()
方法的作用类似于in
操作符。
1 2 3 4 5 6 7 8 9
| 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'));
|
核心代码
自定义keyExists
函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 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; }
console.log(keyExists('apple', ['apple', 'banana', 'orange'])); console.log(keyExists('fruit', ['apple', 'banana', 'orange'])); console.log(keyExists('age', {'name': 'Bill', 'age': 29 })); console.log(keyExists('title', {'name': 'Jason', 'age': 29 }));
|
ES6解决方案
1 2 3 4 5 6 7 8 9
| 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');
|
可选链操作符示例
1 2 3 4
| 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的_.get
方法示例
1 2 3 4 5 6 7
| var object = { 'a': [{ 'b': { 'c': 3 } }] }; console.log( _.get(object, 'a[0].b.c'), _.get(object, ['a', '0', 'b', 'c']), _.get(object, 'a.b.c'), _.get(object, 'a.b.c', 'default') );
|
最佳实践
- 尽量避免对象中使用
undefined
值,使用null
来初始化属性值。这样可以直接检查值是否为undefined
来判断键是否存在。 - 如果需要检查对象自身的属性,优先使用
Object.hasOwn()
方法,因为它可以处理一些特殊情况,如使用Object.create(null)
创建的对象。 - 如果只需要简单检查键是否存在,
in
操作符是一个不错的选择。
常见问题
1. 直接检查值是否为undefined
有什么问题?
如果键存在但对应的值为undefined
,直接检查值是否为undefined
会得到错误的结果,误以为键不存在。例如:
1 2
| var obj = { key: undefined }; console.log(obj["key"]!== undefined);
|
2. Object.hasOwn()
和Object.hasOwnProperty()
有什么区别?
Object.hasOwn()
是Object.hasOwnProperty()
的替代方法,它可以处理使用Object.create(null)
创建的对象以及重写了hasOwnProperty()
方法的对象。例如:
1 2 3 4 5 6 7 8 9 10
| let person = { hasOwnProperty: function() { return false; }, age: 35 };
if (Object.hasOwn(person, 'age')) { console.log(person.age); }
|
3. Reflect.has()
方法的性能如何?
Reflect.has()
方法的性能比其他一些方法(如in
操作符和Object.hasOwn()
)稍慢。如果在代码中只使用几次,性能差异可以忽略不计;但如果需要大量使用,建议选择其他性能更好的方法。