Hi I have this simple code:
let obj = {
games: [
{id: 'test'}
]
}
console.log(obj.games[0].id) // returns: test
console.log('games[0].id' in obj) // returns: false
console.log(obj.hasOwnProperty('games[0].id')) // returns: false
I don't understand the return value when I try to check for its property name instead of returning its property value.
CodePudding user response:
in
and hasOwnProperty()
just take a single property name, they don't accept an expression with nested properties.
So you have to test each level separately.
console.log('games' in obj && 0 in obj.games && "id" in obj.games[0])
You can also use optional chaining to combine all but the last check.
console.log(obj?.games.?[0] && "id" in obj.games[0])
CodePudding user response:
The in
operator can only test a single attribute. It's not intelligent enough to follow a path.
You could just
const value = obj?.games?.[0]?.id;
const exists = value !== undefined;
console.log(exists)
More importantly, in this case you really shouldn't use the in
operator at all. The disadvantage of the in
operator, is that it requires the tested field to be coded as a string.
In general putting the names of fields in strings is something to avoid, because it makes it harder to find usages and to refacture code later on.
The use of the in
operator can only be justified if the name of the tested field is not a constant, not known in advance.
Having said that, the hasOwnProperty
function does something slightly different. It is actually more strict than the solution presented above, and also more strict than the in
operator. It strictly checks for fields on the object itself, not the ones of super/base types.
The hasOwnProperty() method returns true if the specified property is a direct property of the object — even if the value is null or undefined. The method returns false if the property is inherited, or has not been declared at all. Unlike the in operator, this method does not check for the specified property in the object's prototype chain. (source: MDN)