3

In a JavaScript app, suppose I have a nested object like this:

var myObject = {
    someProp: {
        someOtherProp: {
            anotherOne: {
                yetAnother: {
                    myValue: "hello!"
                }
            }
        }
    }
}

In another part of the code, I'm calling myValue multiple times (I just call it three times in this example but imagine there's a lot more):

someFunc() {
    doSomething(myObject.someProp.someOtherProp.anotherOne.yetAnother.myValue)

    doSomethingElse({
        arg1: "something",
        arg2: myObject.someProp.someOtherProp.anotherOne.yetAnother.myValue
    })

    if (myObject.someProp.someOtherProp.anotherOne.yetAnother.myValue == "hola") {
        doStuff()
    }

}

Apart from the obvious readability and maintainability gains, is it actually faster to do it like this:

someFunc() {
    let val = myObject.someProp.someOtherProp.anotherOne.yetAnother.myValue

    doSomething(val)

    doSomethingElse({
        arg1: "something",
        arg2: val
    })

    if (val == "hola") {
        doStuff()
    }

}

Or is it pretty much the same, behind the scenes?

In other words, does the interpreter have to walk the whole myObject tree and search for each nested property each time, in case 1, or does it somehow cache the value, or is there another mechanism that makes it as fast as case 2?

Context: any modern browser (Chrome, Safari, Firefox, Edge).

Jivan
  • 315

3 Answers3

7

Well, on the most basic level, val has fewer characters in it than myObject.someProp.someOtherProp.anotherOne.yetAnother.myValue so, simply parsing it will be (trivially) faster.

On the specification level, myObject.someProp.someOtherProp.anotherOne.yetAnother.myValue is the equivalent of myObject["someProp"]["someOtherProp"]["anotherOne"]["yetAnother"]["myValue"] which implies a lookup at each level. But, you knew that.

So, the question is, "Do some modern browsers' JavaScript engines handle this as a special case?"

My opinion (wild-ass guess) is a) Probably Not, b) if they do, it would be for one, maybe two levels, not five. c) support would vary wildly amongst the different browsers, and, most importantly, d) the browser vendors will never give you specifics about it, because if they did, they'd be bound to support that implementation detail forever.

James Curran
  • 1,809
6

The optimization you are performing by hand is called common subexpression elimination. According to this article, Chrome's V8 has performed this operation since at least 2011; Webkit's JIT also does it; SpiderMonkey, the JS engine in Firefox also does it. I haven't found a good description of the optimization performed by Chakra, Edge's JIT, but the source code is online and the function located here appears to perform the relevant optimization.

It therefore seems that there is little point in doing this for optimization purposes (at least for desktop browsers -- note that mobile browsers in many cases do not have JIT compilers, or if they do they are much more basic). But it's probably worth doing anyway in order to make your code more readable.

Jules
  • 17,880
  • 2
  • 38
  • 65
2

For speed: Measure.

However, the temporary variable has the huge advantage that as a reader, I know that all the places using the temporary value use the same actual value. If the same very long expression is used in multiple places, I don't know for sure that (a) the very long expression is actually the same in each place or has a subtle difference (for example, there could be "yetAnother" used in one expression and "yetanother" in another), (b) the very long expression has no side effects so executing it multiple times is different from executing it once, (c) none of the code running in between does anything that changes the result of evaluating the expression.

In many development systems, it may also be easier during debugging to see the value of the very long expression when it is stored in a variable. If during debugging I want to see how the very long expression is evaluated, I need to set a breakpoint in one place only. If the very long expression changes due to changed requirements, I have only one place to change. So it is often better to use a variable. In the three cases mentioned above (slight differences, execution has wanted side effects, value may change) that would be something unexpected and would need commenting so nobody changes the code.

gnasher729
  • 49,096