Qual è la convenzione JavaScript per nessuna operazione?

Qual è la convenzione JavaScript per nessuna operazione?

  • Un’opzione è semplicemente una funzione vuota: function() {}
  • jQuery offre $.noop() , che chiama semplicemente la funzione vuota sopra.
  • È accettabile inserire semplicemente un valore di false o 0 ?

Nel contesto … tutti questi funzionano senza generare un errore in Chrome:

 var a = 2; (a === 1) ? alert(1) : function() {}; (a === 1) ? alert(1) : $.noop(); (a === 1) ? alert(1) : false; (a === 1) ? alert(1) : 0; 

EDIT: Un sacco di gente ha risposto con “non farlo! Cambia la struttura del codice!” Questo mi ricorda un post in cui qualcuno ha chiesto come annusare il browser. Ha ricevuto una raffica di messaggi dicendo: “NON FARE QUESTO! È MALE”, ma nessuno gli ha detto come annusare il browser . Questa non è una recensione del codice. Immagina di avere a che fare con un codice legacy che non può essere modificato e che, senza alcune funzioni passate, genererà un errore. O, semplicemente, questo è il modo in cui il cliente lo vuole, e mi stanno pagando . Quindi, rispettosamente, per favore rispondi alla domanda : qual è il modo migliore per specificare una funzione “nessuna operazione” in JavaScript?

EDIT2: Che ne dici di uno di questi?

 true; false; 0; 1; null; 

Per rispondere alla domanda originale, l’implementazione più elegante e ordinata di una funzione noop in puro Javascript (come è anche discusso qui ) è Function.prototype . Lo snippet seguente mostra il suo utilizzo:

 setTimeout(Function.prototype, 10000); 

Tutti e tre i browser (Chrome, Firefox e IE 11) non fanno in modo che l’interprete ritorni dopo 10 secondi durante l’esecuzione di quanto sopra (puoi testare passo per passo usando la modalità “passaggio” nel debugger).

Anche se questo è un “vero e proprio noop” dal momento che la maggior parte dei browser sembra non eseguire nulla per eseguire il noop definito in questo modo (e quindi risparmia i cicli della CPU), potrebbero esserci alcuni problemi di prestazioni associati a questo (come è menzionato anche da altri nei commenti o in altre risposte).

Tuttavia, detto questo, è ansible definire facilmente la propria funzione noop e, infatti, molte librerie e framework forniscono anche funzioni noop. Di seguito sono riportati alcuni esempi:

 var noop = function () {}; // Define your own noop in ES3 or ES5 const noop = () => {}; // OR Define your own noop in ES6 setTimeout(noop, 10000); // Using the predefined noop setTimeout(function () {} , 10000); // Using directly in ES3 or ES5 setTimeout(() => {} , 10000); // Using directly in ES6 as Lambda (arrow function) setTimeout(angular.noop, 10000); // Using with angular 1.x setTimeout(jQuery.noop, 10000); // Using with jQuery 

Ecco un elenco alfabetico delle varie implementazioni delle funzioni di noop (o discussioni correlate o ricerche su google):

Angular 1.x , Angular 2+ (Non sembra avere un’implementazione nativa – usa la tua come mostrato sopra), Ember , jQuery , Lodash , NodeJS , Ramda , React (Non sembra che abbia un’implementazione nativa – usa la tua come mostrato sopra), RxJS , Underscore

BOTTOM LINE : Sebbene Function.prototype sia un modo elegante per esprimere un noop in Javascript, tuttavia, potrebbero esserci alcuni problemi di prestazioni relativi al suo utilizzo. Quindi, puoi definire e usare il tuo (come mostrato sopra) o usarne uno definito dalla libreria / framework che potresti usare nel tuo codice.

Il noop più conciso e performante è una funzione a freccia vuota : ()=>{} .

Le funzioni freccia funzionano in modo nativo in tutti i browser eccetto IE (c’è una trasformazione babel, se necessario): MDN


()=>{} vs. Function.Prototype

  • ()=>{} è 87% più veloce di Function.prototype in Chrome 67.
  • ()=>{} è 25% più veloce di Function.prototype in Firefox 60.
  • ()=>{} è 85% più veloce di Function.prototype in Edge (15/6/2018) .
  • ()=>{} è il 65% in meno di codice di Function.prototype .

Il test qui sotto si riscalda usando la funzione freccia per dare bias a Function.prototype , tuttavia la funzione freccia è il chiaro vincitore:

 const noop = ()=>{}; const noopProto = Function.prototype; function test (_noop, iterations) { const before = performance.now(); for(let i = 0; i < iterations; i++) _noop(); const after = performance.now(); const elapsed = after - before; console.info(`${elapsed.toFixed(4)}MS\t${_noop.toString().replace('\n', '')}\tISNOOP? ${_noop() === undefined}`); return elapsed; } const iterations = 10000000 console.info(`noop time for ${iterations.toLocaleString()} iterations`) const timings = { noop: test(noop, iterations), noopProto: test(noopProto, iterations) } const percentFaster = ((timings.noopProto - timings.noop)/timings.noopProto).toLocaleString("en-us", { style: "percent" }); console.info(`()=>{} is ${percentFaster} faster than Function.prototype in the current browser!`) 

tutto ciò che tendi a raggiungere qui è sbagliato. Le espressioni ternarie non devono essere utilizzate come una dichiarazione completa, solo nell’espressione, quindi la risposta alla tua domanda è:

nessuno dei tuoi suggerimenti, invece, fa:

 var a = 2; if (a === 1) alert(1) // else do nothing! 

quindi il codice è facilmente comprensibile, leggibile e il più efficiente ansible.

Perché renderlo più difficile, quando può essere semplice?

modificare:

Quindi, un comando “nessuna operazione” indica fondamentalmente una struttura di codice inferiore?

Ti manca il mio punto. Tutto quanto sopra riguarda l’espressione ternaria x ? y : z x ? y : z .

Ma un comando di nessuna operazione non ha senso in linguaggi di livello superiore come Javascript.

Di solito viene utilizzato, in linguaggi di livello inferiore come assembly o C, come un modo per fare in modo che il processore non faccia nulla per una sola istruzione a scopo di temporizzazione.

In JS, se fai 0; , null; , function () {}; o un’istruzione vuota, ci sono grandi possibilità che venga ignorata dall’interprete quando la legge, ma prima che venga interpretata, quindi alla fine, il tuo programma verrà caricato più lentamente di una quantità davvero piccola di tempo. Nota Bene : Sto assumendo questo, poiché non sono coinvolto in alcun interprete JS ampiamente utilizzato, e ci sono possibilità che ogni interprete abbia una propria strategia.

Nel caso in cui tu usi qualcosa di un po ‘più complicato, come $.noop() o var foo = function () {}; foo() var foo = function () {}; foo() , quindi l’interprete può eseguire una chiamata di funzione non utile che finirà per rovinare alcuni byte dello stack di funzioni e alcuni cicli.

L’unica ragione per cui sarebbe presente una funzione come $.noop() sarebbe quella di poter comunque assegnare una funzione di callback a una funzione di evento che genererebbe un’eccezione se non può chiamare quella richiamata. Ma poi, è necessariamente una funzione che devi dare, e dargli il nome di noop è una buona idea, quindi stai dicendo ai tuoi lettori (e potresti essere tu tra sei mesi) che di proposito hai dato una funzione vuota.

Alla fine, non esiste una struttura di codice “inferiore” o “superiore”. Hai ragione o torto nel modo in cui usi i tuoi strumenti. Usare un ternario per il tuo esempio è come usare un martello quando vuoi avvitare. Funzionerà, ma non sei sicuro di poter appendere qualcosa a quella vite.

Ciò che potrebbe essere considerato “inferiore” o “superiore” è l’algoritmo e le idee che inserisci nel tuo codice. Ma questa è un’altra cosa.

Penso che jQuery noop() sia principalmente inteso a prevenire il crash del codice fornendo una funzione predefinita quando quella richiesta non è disponibile. Ad esempio, considerando il seguente esempio di codice, $.noop viene scelto se fakeFunction non è definito, impedendo la prossima chiamata a fn da arresto anomalo:

 var fn = fakeFunction || $.noop; fn() // no crash 

Quindi, noop() consente di risparmiare memoria evitando di scrivere la stessa funzione vuota più volte in tutto il codice. A proposito, $.noop è un po ‘più corto di function(){} (6 byte salvati per token). Quindi, non esiste alcuna relazione tra il codice e il modello di funzione vuoto. Usa null , false o 0 se vuoi, nel tuo caso non ci saranno effetti collaterali. Inoltre, vale la pena notare che questo codice …

 true/false ? alert('boo') : function(){}; 

… è completamente inutile dato che non chiamerai mai la funzione, e questa …

 true/false ? alert('boo') : $.noop(); 

… è ancora più inutile dato che chiami una funzione vuota, che è esattamente la stessa di …

 true/false ? alert('boo') : undefined; 

Sostituiamo l’espressione ternaria con un’istruzione if per vedere quanto è inutile:

 if (true/false) { alert('boo'); } else { $.noop(); // returns undefined which goes nowhere } 

Potresti semplicemente scrivere:

 if (true/false) alert('boo'); 

O ancora più corto:

 true/false && alert('boo'); 

Per rispondere alla fine alla tua domanda, suppongo che una “operazione non convenzionale” sia quella che non viene mai scritta.

Io uso:

  (0); // nop 

Per testare il tempo di esecuzione di questa esecuzione come:

 console.time("mark"); (0); // nop console.timeEnd("mark"); 

risultato: segno: 0,000ms

Usare Boolean( 10 > 9) può essere ridotto a semplicemente ( 10 > 9) che restituisce true . Venendo con l’idea di usare un singolo operando mi aspettavo completamente (0); restituirebbe false , ma restituisce semplicemente l’argomento indietro come può essere verificato eseguendo questo test sulla console.

 > var a = (0); < undefined > a < 0