14

我在一个自动生成的 javascript 文件中看到了这一点:

function map(x){
    x={x:x};
    delete x.x;
    return x
}

我的结论是用于创建对象,但为什么要这样创建呢?它是一种模式吗?

更新

更多信息,创建此代码的工具是来自 Google 的 dart2js,代码在此上下文中使用:

(function (reflectionData) {
  function map(x){x={x:x};delete x.x;return x}
  if (!init.libraries) init.libraries = [];
  if (!init.mangledNames) init.mangledNames = map();
  if (!init.mangledGlobalNames) init.mangledGlobalNames = map();
  if (!init.statics) init.statics = map();
  if (!init.interfaces) init.interfaces = map();
4

3 回答 3

11

在 dart 源代码中,有一条评论说这种技术用于 v8 性能原因:

// [map] returns an object literal that V8 shouldn't try to optimize with a
// hidden class. This prevents a potential performance problem where V8 tries
// to build a hidden class for an object used as a hashMap.

https://github.com/dart-lang/bleeding_edge/blob/4dde22bc006605fc168cefcc0807c43354463b6e/dart/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart#L17-L19

这里的词map指的是关联数组

于 2013-10-08T19:17:39.473 回答
10

前段时间我读过一篇关于这个的文章,如果你delete从一个对象中获取一些东西,V8会将对象置于字典模式慢速模式,然后属性存储在“哈希表”中。

V8 可以很好地处理这样的细微差异,但是如果您的代码以不特定的顺序将各种随机属性分配给来自同一个构造函数的对象,或者如果您删除属性,V8 会将对象放入存储属性的字典模式在哈希表中。这可以防止分配荒谬数量的地图。

这是文章http://www.jayconrod.com/posts/52/a-tour-of-v8-object-representation它在那里解释了它以及其他内容。

我可能错了,但我认为这用于大型(大小和寿命)对象以提高性能并减少内存泄漏的机会。

这是同一主题

使用 delete 关键字会影响对象的 v8 优化吗?

于 2013-10-08T19:19:13.810 回答
9

map函数的目的是创建一个关联映射对象,其属性集可以快速更改。

很自然的问题出现了:默认情况下,不是所有的 JavaScript 对象都已经映射了吗?对,他们是!EMCAScript 规范允许对象随时添加或删除属性,从而允许它们充当关联映射。

但是,唉,负责实现 JavaScript 执行环境的低级语言(可能是 C++)并不那么容易。特别是,V8 使用了一个名为hidden classes的概念,向 JavaScript 对象添加属性将导致创建新的 C++ 类。V8 这样做是为了优化,因为它假设您的代码将重复使用一小组对象类型。

例如,您有一个Bullet具有xydxdy属性的类型。实际上,这些类型是固定的;您不太可能突然在动态中为Bullet对象添加新属性。隐藏类优化意味着使用一组固定的对象类型运行速度非常快,但这也意味着,有时,为 JS 对象添加新属性的实际成本可能相当高,因为它会提示创建一个具有新属性的新 C++ 类。

通过在对象上引入delete操作x,您向 V8 引擎发出信号,表明该对象x不会从隐藏类优化中受益。隐藏类背后的想法是您的对象通常不会更改其属性集(除了在构造时添加新属性)。通过这样做,delete您明确表示该对象将以使隐藏类完全无用的方式更改其属性集。对于这个对象,创建隐藏类的成本远远超过了收益。

因此,返回的对象map将被排除在 V8 隐藏类优化之外,允许它更快地添加和删除任意属性。

于 2013-10-08T19:36:31.693 回答