性能也是一个原因。有时您可能需要遍历键。做这件事有很多种方法
for (let key in object) { ... }
for (let key in object) { if (object.hasOwnProperty(key) { ... } }
for (let key of Object.keys(object)) { ... }
我通常使用for of Object.keys()
它做正确的事情并且相对简洁,无需添加检查。
但是,它要慢得多。
只是猜测原因Object.keys
很慢很明显,Object.keys()
必须进行分配。事实上,AFAIK 它必须分配所有密钥的副本。
const before = Object.keys(object);
object.newProp = true;
const after = Object.keys(object);
before.join('') !== after.join('')
JS 引擎可能会使用某种不可变键结构,以便Object.keys(object)
返回一个引用,该引用迭代不可变键并object.newProp
创建一个全新的不可变键对象,但无论如何,它显然会慢 15 倍
甚至检查hasOwnProperty
速度也慢了 2 倍。
所有这一切的重点是,如果您有性能敏感的代码并且需要遍历键,那么您希望能够使用for in
而无需调用hasOwnProperty
. 只有在未修改的情况下才能执行此操作Object.prototype
请注意,如果您使用Object.defineProperty
修改原型,如果您添加的东西不可枚举,那么它们不会影响 JavaScript 在上述情况下的行为。不幸的是,至少在 Chrome 83 中,它们确实会影响性能。
我添加了 3000 个不可枚举的属性,只是为了试图强制出现任何性能问题。只有 30 个属性,测试太接近了,无法判断是否有任何性能影响。
https://jsperf.com/does-adding-non-enumerable-properties-affect-perf
Firefox 77 和 Safari 13.1 显示增强和未增强类之间的性能没有差异,也许 v8 将在这方面得到修复,您可以忽略性能问题。
但是,让我也补充一下,还有一个故事Array.prototype.smoosh
。简短的版本是 Mootools,一个流行的库,他们自己制作了Array.prototype.flatten
. 当标准委员会试图添加本地人Array.prototype.flatten
时,他们发现不能不破坏很多网站。发现中断的开发人员建议将 es5 方法命名smoosh
为一个笑话,但人们吓坏了,不明白这是个笑话。他们决定flat
而不是flatten
这个故事的寓意是你不应该扩展原生对象。如果你这样做了,你可能会遇到同样的问题,除非你的特定库碰巧像 MooTools 一样受欢迎,否则浏览器供应商不太可能解决你造成的问题。如果您的库确实如此受欢迎,那么强迫其他人解决您引起的问题将是一种卑鄙的做法。所以,请不要扩展本机对象