I know some people's gut reaction to this would be to say "Just use a Map", but, sometimes a map isn't the appropriate data structure, like when you're dealing with an object where the keys are already known in advance (e.g. an instance of a class). Take this example:
class User {
constructor({ name, birthday }) {
this.name = name
this.birthday = birthday
}
}
function getUserAttr(user, attr) {
return user[attr]
}
const user = new User({ name: 'Sally', birthday: '1/2/1999' })
const userSuppliedKey = 'toString'
console.log(getUserAttr(user, userSuppliedKey)) // Whoops, a bug!
Right now, the recommended way to fix this issue is to redefine getUserAttr() as follows:
function getUserAttr(user, attr) {
if (Object.prototype.hasOwnProperty.call(user, attr)) {
return user[attr]
}
return undefined
}
Can't we provide some native functionality that's, you know, a little less hacky?
Here's what I propose:
Object.containsOwnProperty(obj, key)
Returns true if the obj parameter contains the key (as an own property). Object.containsOwnProperty(obj, key)
would behave exactly the same as Object.prototype.hasOwnProperty.call(obj, key)
Example:
> Object.containsOwnProperty({ x: 2 }, 'x')
true
> Object.containsOwnProperty({ x: 2 }, 'toString')
false
Object.getOwnProperty(obj, key)
If the obj parameter contains the key (as an own property), then the associated value is returned, otherwise, undefined is returned.
Example:
> Object.getOwnProperty({ x: 2 }, 'x')
2
> Object.getOwnProperty({ x: 2 }, 'toString')
undefined
Name bikeshedding
"containsOwnProperty" was the best name I could think of, given "hasOwnProperty" already exists on Object's prototype.
Some other potential name combinations:
Object.has()/Object.get() // Works, but I would really like to have the word "own" in there somewhere.
Object.hasOwn()/Object.getOwn() // That works. It's a little awkward.
Object.isOwnProperty()/Object.getOwnProperty() // Also works
Other suggestions are welcome.