javascript - 为什么 Object.create 比构造函数慢那么多?

标签 javascript performance constructor object-create

背景

在我维护的一个项目中,我们广泛使用 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/

相关文章:

javascript - 所有浏览器中渐变颜色的动态变化

javascript - html 按钮只在页面上的某些地方起作用?

javascript - 如果我将相同的事件附加到相同的元素会发生什么?

javascript - 有人可以将这个简单的函数翻译成Javascript吗?

c++ - VS 2017 和 2019 运行 c++ 真的很慢

performance - GLSL:为什么 const int 数组比普通数组慢这么多?

c++ - 当第二个依赖于第一个时,如何在构造函数初始值设定项列表中初始化两个 std::array

performance - Grails 1.0 到 1.3 - 速度增加?

java - 无法将上下文从主 Activity 传递到 AsyncTask 以显示 AlertDialog - Android/Java

java - 异常类的默认构造函数?