È meglio avere il rendimento atteso all'inizio o alla fine di una funzione?

2

Questa è una funzione che ricerca i nodi figli in modo ricorsivo finché non trova uno che è un testo:

_.findPrevText = (node) => {
  if (node.nodeType === 3) return node
  return _.findPrevText(node.lastChild)
}

Potrei anche scriverlo in questo modo:

_.findPrevText = (node) => {
  if (node.nodeType !== 3) return _.findPrevText(node.lastChild)
  return node
}

Quale stile è più pulito / leggibile (o ha prestazioni migliori)?

    
posta alex 04.05.2016 - 17:59
fonte

2 risposte

5

In termini di velocità di esecuzione sono uguali. Il codice compilato / interpretato sta per fare un test se nodetype == 3. Se sì, esegue una dichiarazione di ritorno successiva. Se no, esegue l'altra dichiarazione di ritorno successiva. Entrambi i casi eseguiranno una dichiarazione di ritorno successiva.

In termini di utilizzo dello stack, sono uguali. In entrambi gli esempi mostrati, cade solo nella chiamata ricorsiva se non può corrispondere a nodetype == 3. È possibile scrivere male il codice in modo che avvengano chiamate ricorsive non necessarie. Ma questo non è il caso negli esempi mostrati. Quindi l'utilizzo della memoria è lo stesso.

Se null è un possibile valore per nodetype, sono sempre gli stessi. I due esempi verranno entrambi inseriti nella chiamata ricorsiva, sia se nodetype == 2 o nodetype == null. È possibile riscrivere gli esempi per verificare anche null e non cadere in ricorsione su valori null. Ma quella non era la domanda posta.

L'unica differenza potrebbe essere la leggibilità. Quale è più leggibile? Le affermazioni positive richiedono un passo mentale in meno (nodetype == 3) è un lavoro un po 'meno mentale di (nodetype! = 3). Ma marginalmente così.

    
risposta data 04.05.2016 - 18:28
fonte
2

È normale nelle funzioni ricorsive scrivere prima il caso base. Ciò significa la tua prima opzione. La tua seconda opzione sta testando l'inverso del caso base, che è fonte di confusione da leggere. Scrivere il caso base per prima cosa fa poca differenza in questo caso particolare, ma nel caso generale, se si dovesse utilizzare la corrispondenza dei pattern, o un'istruzione switch o una catena if-else, è solitamente molto più pulito scrivere prima il caso base. Inoltre, il caso ricorsivo è spesso molto più prolisso del caso base. Da qui la convenzione.

Si noti che la convenzione non ha nulla a che fare con la ricorsione della coda, poiché entrambe le opzioni sono ricorsive della coda. La ricorsione della coda non richiede che la chiamata ricorsiva sia l'ultima espressione scritta fisicamente nel corpo della funzione. Richiede che sia l'ultima espressione valutata prima di tornare dalla funzione, il che è vero in entrambi i casi. In ogni caso, è un punto critico in JavaScript, perché, per quanto ne so, nessun motore JavaScript usato comunemente fa un'eliminazione di chiamate tail.

    
risposta data 04.05.2016 - 18:40
fonte

Leggi altre domande sui tag