Perf is also a reason. Sometimes you might need to loop over keys. There are several ways to do this
for (let key in object) { ... }
for (let key in object) { if (object.hasOwnProperty(key) { ... } }
for (let key of Object.keys(object)) { ... }
I usually use for of Object.keys()
as it does the right thing and is relatively terse, no need to add the check.
But, it's much slower.
Just guessing the reason Object.keys
is slow is obvious, Object.keys()
has to make an allocation. In fact AFAIK it has to allocate a copy of all the keys since.
const before = Object.keys(object);
object.newProp = true;
const after = Object.keys(object);
before.join('') !== after.join('')
It's possible the JS engine could use some kind of immutable key structure so that Object.keys(object)
returns a reference something that iterates over immutable keys and that object.newProp
creates an entirely new immutable keys object but whatever, it's clearly slower by up to 15x
Even checking hasOwnProperty
is up to 2x slower.
The point of all of that is that if you have perf sensitive code and need to loop over keys then you want to be able to use for in
without having to call hasOwnProperty
. You can only do this if you haven't modified Object.prototype
note that if you use Object.defineProperty
to modify the prototype if the things you add are not enumerable then they won't affect the behavior of JavaScript in the above cases. Unfortunately, at least in Chrome 83, they do affect performance.
I added 3000 non-enumerable properties just to try to force the any perf issues to appear. With only 30 properties the tests were too close to tell if there was any perf impact.
https://jsperf.com/does-adding-non-enumerable-properties-affect-perf
Firefox 77 and Safari 13.1 showed no difference in perf between the Augmented and Unaugmented classes maybe v8 will get fixed in this area and you can ignore the perf issues.
But, Let me also add there is the story of Array.prototype.smoosh
. The short version is Mootools, a popular library, made their own Array.prototype.flatten
. When the standards committee tried to add a native Array.prototype.flatten
they found the couldn't without breaking lots of sites. The devs who found out about the break suggested naming the es5 method smoosh
as a joke but people freaked out not understanding it was a joke. They settled on flat
instead of flatten
The moral of the story is you shouldn't extend native objects. If you do you could run into the same issue of your stuff breaking and unless your particular library happens to be as popular as MooTools the browser vendors are unlikely to work around the issue you caused. If your library does get that popular it would be kind of mean to force everyone else work around the issue you caused. So, please Don't Extend Native Objects
var x = {}
creates a native object. E.g. see ECMA-262 ed 5 §4.3.6. – Pulpittsw_
, and the chances of collision becomes so low that it's almost insignificant. developer.apple.com/library/archive/documentation/Cocoa/… – Pageantrytrim()
method did exactly the same thing as the native one does now. What if it didn't (e.g. used different parameter)? – Mavilia