È più veloce creare una variabile dedicata invece di chiamare più volte l'oggetto nidificato profondamente?

3

In un'app JavaScript, supponiamo di avere un oggetto nidificato come questo:

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

In un'altra parte del codice, sto chiamando myValue più volte (lo chiamo tre volte in questo esempio ma immagino ci sia molto di più):

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()
    }

}

A parte l'ovvia leggibilità e guadagni di manutenibilità , è più veloce farlo in questo modo:

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

    doSomething(val)

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

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

}

O è più o meno lo stesso, dietro le quinte?

In altre parole, l'interprete deve percorrere l'intero albero myObject e cercare ogni proprietà annidata ogni volta, nel caso 1, o memorizza in qualche modo il valore, oppure esiste un altro meccanismo che lo rende veloce come nel caso 2?

Contesto: qualsiasi browser moderno (Chrome, Safari, Firefox, Edge).

    
posta Jivan 13.07.2016 - 14:31
fonte

3 risposte

6

L'ottimizzazione che stai eseguendo a mano si chiama eliminazione di sottoespressione comune . Secondo questo articolo , il V8 di Chrome ha eseguito questa operazione almeno dal 2011; Anche JIT di Webkit lo fa ; SpiderMonkey, anche il motore JS in Firefox lo fa . Non ho trovato una buona descrizione dell'ottimizzazione eseguita da Chakra, JIT di Edge, ma il codice sorgente è online e la funzione si trova qui sembra eseguire l'ottimizzazione pertinente.

Sembra quindi che ci sia poco da fare a scopo di ottimizzazione (almeno per i browser desktop - nota che i browser mobili in molti casi non hanno compilatori JIT, o se lo fanno sono molto più basilari). Ma probabilmente vale la pena farlo comunque per rendere il tuo codice più leggibile.

    
risposta data 14.07.2016 - 00:09
fonte
7

Beh, sul livello più elementare, val ha meno caratteri in esso di myObject.someProp.someOtherProp.anotherOne.yetAnother.myValue quindi, semplicemente analizzarlo sarà (banalmente) più veloce.

A livello di specifica, myObject.someProp.someOtherProp.anotherOne.yetAnother.myValue equivale a myObject["someProp"]["someOtherProp"]["anotherOne"]["yetAnother"]["myValue"] che implica una ricerca per ogni livello. Ma lo sapevi.

Quindi, la domanda è: "I motori JavaScript di alcuni browser moderni gestiscono questo come caso speciale?"

La mia opinione (ipotesi del selvaggio) è a) Probabilmente no, b) se lo fanno, sarebbe per uno, forse due livelli, non cinque. c) il supporto varierà selvaggiamente tra i diversi browser e, soprattutto, d) i produttori di browser non ti forniranno mai dettagli specifici, perché se lo facessero, sarebbero tenuti a supportare per sempre i dettagli dell'implementazione.

    
risposta data 13.07.2016 - 16:24
fonte
2

Per velocità: Misura.

Tuttavia, la variabile temporanea ha l'enorme vantaggio che, come lettore, so che tutti i luoghi che usano il valore temporaneo usano lo stesso valore reale. Se la stessa espressione molto lunga è usata in più punti, non sono sicuro che (a) l'espressione molto lunga sia effettivamente la stessa in ogni luogo o abbia una sottile differenza (ad esempio, potrebbe esserci "ancora un'altra" usata in un'espressione e "yetanother" in un altro), (b) l'espressione molto lunga non ha effetti collaterali quindi eseguirla più volte è diversa dall'esecuzione una volta, (c) nessuno del codice in esecuzione fa qualcosa che cambia il risultato di valutare l'espressione.

In molti sistemi di sviluppo, può anche essere più facile durante il debug per vedere il valore dell'espressione molto lunga quando è memorizzata in una variabile. Se durante il debug voglio vedere come viene valutata l'espressione molto lunga, ho bisogno di impostare un breakpoint in un solo posto. Se l'espressione molto lunga cambia a causa di requisiti modificati, ho solo un posto dove cambiare. Quindi è spesso meglio usare una variabile. Nei tre casi menzionati sopra (piccole differenze, l'esecuzione ha voluto effetti collaterali, il valore potrebbe cambiare) sarebbe qualcosa di inaspettato e avrebbe bisogno di commenti, quindi nessuno cambia il codice.

    
risposta data 14.07.2016 - 10:23
fonte

Leggi altre domande sui tag