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).

9
  • 6
    I'm guessing this is one of those questions, where the only answer is; "the spec doesn't say anything about how the interpreter should implement this feature, so it might already be caching stuff for you", in which case it's a matter of "do what's most readable" and "profile your code to see". Either way, I don't think you really want to think about this, as it seems like a micro-optimization.
    – cwap
    Jul 13, 2016 at 12:42
  • 2
    One reason to do this is to avoid having the variable change between the calls. If it's important that the value stay the same across the calls, you should definitely create a variable. Obviously, if you need to pass in changed values across the calls, this is a bad idea but I would avoid that kind of design because it's extremely hard to follow code like that.
    – JimmyJames
    Jul 13, 2016 at 13:15
  • 1
    Possible duplicate of Is micro-optimisation important when coding?
    – gnat
    Jul 13, 2016 at 13:25
  • 1
    @jivan Curiosity is always nice, and it's a valid question imho. I was just trying to say that you probably shouldn't expect a "good" answer.
    – cwap
    Jul 13, 2016 at 13:30
  • 1
    @Jivan: You're the only one who sees the duplicate header in the question (it is system-generated), and gnat's comment is inconsequential. Jul 13, 2016 at 22:36

3 Answers 3

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.

2
  • 4
    By far most important part - But it's probably worth doing anyway in order to make your code more readable
    – Kromster
    Jul 14, 2016 at 6:52
  • Yes on readability, but strongly suggest a better name than "val" in the actual code. :-)
    – user949300
    Jul 14, 2016 at 21:52
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.

1
  • "if they did, they'd be bound to support that implementation detail forever" except V8 source is available for perusal. They regularly detail current implementations but not in an official manner as to suggest that it's a permanent API or behavior.
    – zzzzBov
    Jul 14, 2016 at 17:52
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.