Search code examples
javascriptoptimizationv8

o[str] vs (o => o.str)


I'm coding a function that takes an object and a projection to know on which field it has to work.

I'm wondering if I should use a string like this :

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


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

foo(o, 'a');

Or with a function :

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

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

I think V8 is creating classes with my javascript objects. If I use a string to access dynamically a field, will it be still able to create a class with my object and not a hashtable or something else ?


Solution

  • V8 developer here. The answer to "which pattern should I use?" is probably "it depends". I can think of scenarios where the one or the other would (likely) be (a bit) faster, depending on your app's behavior. So I would suggest that you either try both (in real code, not a microbenchmark!) and measure yourself, or simply pick whichever you prefer and/or makes more sense in the larger context, and not worry about it until profiling shows that this is an actual bottleneck that's worth spending time on.

    If the properties are indeed known at the call site, then the fastest option is probably to load the property before the call:

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

    I realize that if things actually were this simple, you probably wouldn't be asking this question; if that assumption is true then this is a great example for how simplifications in microbenchmarks can easily change what the right answer is.


    The answer to the classes question is that this decision has no impact on how V8 represents your objects under the hood -- that mostly depends on how you modify your objects, not on how you read from them. Also, for the record:

    • every object has a "hidden class"; whether or not it uses hash table representation is orthogonal to that
    • whether hash table mode or shape-tracking mode is better for any given object is one of the things that depend on the use case, which is precisely why both modes exist. I wouldn't worry too much about it, unless you know (from profiling) that it happens to be a problem in your case (more often than not, V8's heuristics get it right; manual intervention is rarely necessary).