I am confused about why JavaScript works in a certain way.
If I have an Object set to the variable of obj, and if I wanted to list all the keys in the object, I would say
Object.keys(obj)
Why wouldn't it be the following?
obj.keys()
If I was working with an Array it would be arr.pop(). So why not the same syntax for an obj.keys()? Again, why does it have to be Object.keys(obj)?
It's possible to put a keys
method on Object.prototype
so that things work as you're expecting, but it's not a good idea.
Object.prototype.keys = function() {
return Object.keys(this);
};
const obj = {
prop: 'val'
};
const keys = obj.keys();
console.log(keys);
With object keys, the issue is that objects can generally have any sort of keys. The object may even have a key named keys
. So, for example:
const obj = {
name: 'building 1',
keys: 'foo'
}
Here, if you did obj.keys()
, you would get a TypeError
, because the keys
property refers to the property directly on the object, rather than the Object.prototype
method.
Object.prototype.keys = function() {
return Object.keys(this);
};
const obj = {
name: 'building 1',
keys: 'foo'
};
const keys = obj.keys();
console.log(keys);
So, the method to use to get all keys of an object was put on Object
instead, as a static method, rather than a prototype method on Object.prototype
, so as to avoid possible name collisions.
Arrays, on the other hand, are pretty much universally expected to have a certain few methods particular to arrays (like push
), and nothing else. Arrays are not generic objects - you'd pretty much always expect an array to have only array methods, and arrays almost never get arbitrary keys added to them. (If you see code that has this, it's probably code that deserves refactoring.) So, with arrays, there's no real possibility of an array method causing name collisions, like there was with a generic object.
Thus, there's no harm in having Array.prototype.push
, but Object.prototype.keys
could easily cause problems.
In addition to the possibility of the hypothetical keys()
method being shadowed, there's also the possibility that the value is not an instance of Object
at all.
Consider the following example:
// properly define your suggested method
Object.defineProperty(Object.prototype, 'keys', {
configurable: true,
writable: true,
value: function keys () { return Object.keys(this); }
})
const obj = { foo: 'bar', hello: 'world' };
console.log(obj instanceof Object);
// okay
console.log(obj.keys());
const value = Object.create(
null,
Object.getOwnPropertyDescriptors(obj)
);
console.log(value instanceof Object);
// existing approach still works
console.log(Object.keys(value));
// suggested approach fails
console.log(value.keys());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With