【问题标题】:o[str] vs (o => o.str)o[str] 与 (o => o.str)
【发布时间】:2018-02-09 22:47:51
【问题描述】:

我正在编写一个函数,该函数接受一个对象和一个投影来知道它必须在哪个字段上工作。

我想知道我是否应该使用这样的字符串:

const o = {
  a: 'Hello There'    
};


function foo(o, str) {
  const a = o[str];
  /* ... */    
}

foo(o, 'a');

或者用一个函数:

function bar(o, proj) {
  const a = proj(o);
  /* ... */
}

bar(o, o => o.a);

我认为 V8 正在使用我的 javascript 对象创建类。如果我使用字符串动态访问字段,它是否仍然能够使用我的对象而不是哈希表或其他东西创建一个类?

【问题讨论】:

    标签: javascript optimization v8


    【解决方案1】:

    V8 开发人员在这里。 “我应该使用哪种模式?”的答案可能是“取决于”。我可以想到其中一个或另一个(可能)会(有点)更快的场景,具体取决于您的应用程序的行为。因此,我建议您要么尝试两者(在真实代码中,而不是微基准测试!)并测量自己,或者简单地选择您喜欢的和/或在更大的上下文中更有意义的一个,并且不要担心它,直到分析表明这是一个值得花时间解决的实际瓶颈。

    如果属性在调用站点确实是已知的,那么最快的选择可能是在调用之前加载属性:

    function baz(o, str, a) {
      /* ... */
    }
    
    baz(o, "a", o.a);
    

    我意识到如果事情真的这么简单,你可能不会问这个问题;如果这个假设是正确的,那么这是一个很好的例子,说明微基准的简化可以很容易地改变正确的答案。


    类问题的答案是,这个决定对 V8 如何在后台表示您的对象没有影响——这主要取决于您如何修改您的对象,而不是您如何从它们中读取。另外,记录在案:

    • 每个对象都有一个“隐藏类”;它是否使用哈希表表示与之正交
    • 哈希表模式或形状跟踪模式是否更适合任何给定对象是取决于用例的事情之一,这正是两种模式都存在的原因。我不会太担心它,除非您(通过分析)知道这恰好是您的问题(通常情况下,V8 的启发式方法是正确的;很少需要手动干预)。

    【讨论】:

    • 假设投影在一个循环内,因此您在调用站点进行属性访问的明显解决方案不再适用:-)
    • 确实,就我而言,在调用函数之前我不知道使用的字段。如果我理解得很好,总是会创建隐藏类。但是 V8 将如何处理 myobject[variableStr] ?
    • 它将执行属性查找。这当然不如可缓存加载快,但如果替代方法是调用一大组函数中的一个,那么这也不是很快。很难预测哪一个会更快,或者差异是否重要。 --(当然;正如我所写,我希望现实比问题中简化的 sn-ps 更复杂。)
    猜你喜欢
    • 2015-05-24
    • 2012-11-22
    • 2020-10-24
    • 1970-01-01
    • 2012-08-28
    • 1970-01-01
    • 1970-01-01
    • 2012-01-20
    • 1970-01-01
    相关资源
    最近更新 更多