背景
在我维护的一个项目中,我们广泛使用 null 原型(prototype)对象作为(仅字符串键)Maps 的穷人替代品,许多旧的 ES6 之前的浏览器本身不支持它。
基本上,要即时创建一个空原型(prototype)对象,可以使用:
var foo = Object.create(null);
这保证了新对象没有继承的属性,例如“toString”、“constructor”、“__proto__”,这些属性对于这个特定的用例来说是不可取的。
由于这种模式在代码中多次出现,我们想到了编写一个构造函数来创建其原型(prototype)具有空原型(prototype)且没有自己的属性的对象。
var Empty = function () { };
Empty.prototype = Object.create(null);
然后要创建一个没有自己的或继承的属性的对象,可以使用:
var bar = new Empty;
问题
为了提高性能,我编写了一个测试,发现原生 Object.create
方法的执行速度出乎意料地比涉及带有临时原型(prototype)的额外构造函数的方法慢得多,总的来说浏览器:http://jsperf.com/blank-object-creation .
我天真地期望后一种方法会更慢,因为它涉及调用用户定义的构造函数,而这在前一种情况下不会发生。
造成这种性能差异的原因可能是什么?
最佳答案
您一直在调查高度依赖于您运行的特定浏览器版本的内容。以下是我在运行您的 jsperf 测试时得到的一些结果:
在 Chrome 47 中,
new Empty
以 63m ops/sec 的速度运行,而Object.create(null)
以 10m ops/sec 的速度运行。在 Firefox 39 中,
new Empty
以 733m ops/sec 的速度运行,而Object.create(null)
以 1,685m ops/sec 的速度运行。
(上面的“m”表示我们谈论的是数百万。)
那你选哪一个呢? 在一种浏览器中最快的方法在另一种浏览器中最慢。
不仅如此,我们在这里看到的结果很可能会随着新浏览器的发布而改变。例如,我检查了 Object.create< 的实现
在 v8 中。截至 2015 年 12 月 30 日,Object.create
的实现是用 JavaScript 编写的,但是一个 commit recently changed it到 C++ 实现。一旦它进入 Chrome,比较 Object.create(null)
和 new Empty
的结果将会改变。
但这还不是全部......
您只看到了一个方面使用 Object.create(null)
创建一个对象,该对象将用作一种 map (a伪 map )。这个伪 map 的访问时间如何?这是检查 misses 性能的测试和检查 hits 性能的一个.
在 Chrome 47 上,使用
Object.create(null)
创建的对象的命中和未命中情况都快了 90%。在 Firefox 39 上,命中案例的表现都是一样的。至于未命中情况,使用
<Object.create(null)
创建的对象的性能非常好,jsperf 告诉我每秒操作数是“无穷大”。
使用 Firefox 39 获得的结果正是我所期望的。 JavaScript 引擎应该在对象本身中寻找字段。如果命中,则搜索结束,无论对象是如何创建的。如果在对象本身中找不到字段,则 JavaScript 引擎必须检查对象的原型(prototype)。对于使用 Object.create(null)
创建的对象,没有原型(prototype),因此搜索到此结束。对于使用 new Empty
创建的对象,有一个原型(prototype),JavaScript 引擎必须在其中搜索。
现在,在伪 map 的生命周期中,伪 map 创建的频率是多少?它多久被访问一次?除非您处在非常特殊的情况下,否则 map 应该创建一次,但访问多次。 因此,命中和未命中的相对性能对于您的整体性能将更为重要应用程序,然后是创建对象的各种方法的相对性能。
我们还可以查看从这些伪映射中添加和删除键的性能,我们会了解更多信息。话又说回来,也许您有永远不会从中删除键的 map (我有一些这样的 map ),因此删除性能对您的情况可能并不重要。
最终,您应该分析作为一个系统的应用程序以提高应用程序的性能。这样,各种操作的相对重要性< em>在您的实际应用中将反射(reflect)在您的结果中。
关于javascript - 为什么 Object.create 比构造函数慢那么多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34480709/