In JavaScript development, we often need to determine whether a property exists in an object.
Because JavaScript is a relatively loose language, it is difficult for us to do something more strict. For example, there is a problem in the definition of "whether an attribute exists" in JavaScript. When does it exist and when does it count as non-existence? There is no right or wrong answer, but in different contexts and different development needs, the meaning of "existence" is different.
Here I will talk about the five commonly used judgment methods and their problems.
Here’s an example:
const obj1 = { name: 'Andy', age: 21 } const obj2 = { name: 'Alice' } console.log( obj1.age ? '存在' : '不存在' ); // 存在 console.log( obj2.age ? '存在' : '不存在' ); // 不存在
Let’s first talk about the shortcomings of this method
If:
const obj = { name: 'Baby', age: 0 } console.log( obj.age ? '存在' : '不存在' ); // 不存在
In this case, age should "exist", but it will be judged as "does not exist".
So this method cannot be used?
This depends on the development needs of the business.
If you know that in your business development requirements, this attribute cannot be 0, empty string, NaN, undefined, etc., then this judgment is still feasible.
If you put it in a more strict environment, then this method will have flaws.
Let’s give an example first:
const obj1 = { name: 'Andy', age: 21 } const obj2 = { name: 'Alice' } console.log( obj1?.age !== undefined ? '存在' : '不存在' ); // 存在 console.log( obj2?.age !== undefined ? '存在' : '不存在' ); // 不存在
The logic of this comparison is that in JS language, a value that does not exist is undefined.
But in an object, this situation may also occur:
const obj = { name: 'Andy', age: undefined }
In this case, should the age attribute be "exists" or "does not exist"?
It’s hard to say, it still depends on your specific demand environment.
If I say, I need to know whether there is an attribute age in an object, I don’t care what its value is.
We can use this method:
const obj = { name: 'Andy', age: 21 } console.log( Object.keys(obj).includes('age') ? '存在' : '不存在' ); // 存在
Use Object.keys() to get its own enumerable property name for judgment.
There are two keywords here, one is "own" and the other is "enumerable".
For example, there is an object here. Add an attribute name to the object:
const obj = { name: 'Andy' } // `name` 就是 obj 自身的属性 console.log( Object.keys(obj) ); // [ 'name' ]
So what is not an attribute of itself? This is where the “prototype” comes into play. An object has a prototype, and the attributes added to the prototype are not "its own" attributes.
const obj = Object.create( { type: 'human' } ); obj.name = 'Andy'; console.log( obj.name ); // Andy console.log( obj.type ); // human console.log( Object.keys(obj) ); // [ 'name' ]
In this example, how do you determine whether type is an attribute of obj? This is hard to say, right? You can say yes or no. This is the problem caused by the relaxed language environment.
But what you need to know is that in this case, Object.keys() cannot get the properties on the prototype. Because it can only read "own" properties.
Attribute descriptors are mentioned here. Many of my colleagues don’t know that in JS language, in an object, each attribute has a descriptor.
How to read it? Let’s print it and take a look:
const obj1 = { name: 'Andy', age: 21 } const obj2 = { name: 'Alice' } console.log( obj1.age ? '存在' : '不存在' ); // 存在 console.log( obj2.age ? '存在' : '不存在' ); // 不存在
You will find that this descriptor is actually an object, which describes some information about this attribute, such as value, writable, and this (enumerable) enumerable ...
This enumerable defines that attribute and whether it can be enumerated. For example, this attribute can be read during the for...in loop, and the same is true for Object.keys().
If I redefine a property as non-enumerable, then Object.keys() cannot read this property.
const obj = { name: 'Baby', age: 0 } console.log( obj.age ? '存在' : '不存在' ); // 不存在
This involves knowledge about attribute descriptors. This is very important knowledge of the native JS language, and I find that many front-end programmers I know lack this knowledge of native JS.
So what if the attribute you want to judge only needs to be its own attribute, regardless of whether it is enumerable or not? Then you can't use Object.keys(). You can use the following method.
What is the difference between Object.hasOwn() and hasOwnProperty()?
Object.hasOwn() is a method added in ES2022, which is used to check whether the object itself has a certain property and is used to replace the optimization processing of hasOwnProperty. Since this method was added later, compatibility is still an issue. If you only consider new versions of browsers, it can still be used.
These two methods determine the "own" attribute name, so it can be read regardless of whether it is enumerable or not.
const obj1 = { name: 'Andy', age: 21 } const obj2 = { name: 'Alice' } console.log( obj1?.age !== undefined ? '存在' : '不存在' ); // 存在 console.log( obj2?.age !== undefined ? '存在' : '不存在' ); // 不存在
Why use Object.hasOwn(), because the object’s hasOwnProperty() may be modified:
const obj = { name: 'Andy', age: undefined }
If the attribute name you want to judge does not need to be its own and enumerable, a prototype is also acceptable, then the last method should be used.
in operator is used to determine whether a property exists in the object or its prototype chain.
const obj = { name: 'Andy', age: 21 } console.log( Object.keys(obj).includes('age') ? '存在' : '不存在' ); // 存在
These methods do not say which method is correct or which is wrong. Not every scenario is suitable for the same approach, adhere to best practices depending on the situation to enhance code readability and security.
The above is the detailed content of [Every Breakthrough] How to determine whether a property exists in JavaScript. For more information, please follow other related articles on the PHP Chinese website!