2009-12-18 20 views
31

Eventuali duplicati:
Are there legitimate uses for JavaScript’s “with” statement?"con" parola chiave in javascript

di recente ho scoperto che in javascript, si può fare qualcosa di simile al seguente:

with document{ 
    write('foo'); 
    body.scrollTop = x; 
} 

Il lato negativo di questo è che ogni variabile deve essere controllata per vedere se appartiene all'oggetto del documento, creando un sovraccarico significativo.

In alternativa, si potrebbe fare qualcosa di simile:

var d = document; 
d.write('foo'); 
d.body.scrollTop = x; 

Esistono situazioni in cui l'uso della 'con' parola chiave è giustificata?

risposta

12

Ecco alcuni post del blog a sostegno del con parola chiave. Ma per favore leggi l'articolo sul blog di YUI che anche Azazul ha pubblicato!

http://webreflection.blogspot.com/2009/12/with-worlds-most-misunderstood.html http://webreflection.blogspot.com/2009/12/with-some-good-example.html

+0

@Abel, hai ragione, questo risponde alla mia domanda piacevolmente oltre ad attirare un avvertimento gigante anche lì. –

+3

@Annie: Penso che dovresti incollare alcune virgolette qui invece di collegare semplicemente due articoli correlati. Cosa succede se portano a un codice HTTP 404 (o simile) in seguito (ad esempio perché questi articoli sono stati spostati/eliminati)? – Sk8erPeter

+1

** L'uso di 'with' non è raccomandato ed è proibito nella modalità rigorosa ECMAScript 5. L'alternativa consigliata è assegnare l'oggetto di cui si desidera accedere a una variabile temporanea. ** Fonte: [Mozilla Developer Network] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Dichiarazioni/con) – Pankaj

50

Basta non ne fanno uso: with dichiarazione http://yuiblog.com/blog/2006/04/11/with-statement-considered-harmful/

di JavaScript aveva lo scopo di fornire una scorciatoia per la scrittura ricorrenti accessi agli oggetti. Così, invece di scrivere

ooo.eee.oo.ah_ah.ting.tang.walla.walla.bing = true; 
ooo.eee.oo.ah_ah.ting.tang.walla.walla.bang = true; 

È possibile scrivere

with (ooo.eee.oo.ah_ah.ting.tang.walla.walla) { 
    bing = true; 
    bang = true; 
} 

che assomiglia molto più bello. Tranne una cosa. Non c'è modo che tu possa capire guardando il codice che bing e bang verranno modificati. Sarà modificato ooo.eee.oo.ah_ah.ting.tang.walla.walla? Oppure le variabili globali bing e bang si riempiono di cianfrusaglie? È impossibile sapere con certezza ...

Se non puoi leggere un programma ed essere sicuro di sapere cosa farà, non puoi avere la certezza che funzionerà correttamente. Per questo motivo, la dichiarazione with dovrebbe essere evitato ...

+2

Non riesco a esprimerlo abbastanza: qualsiasi sintassi "with" -like, come quella per JavaScript e Delphi, in cui non si specifica esplicitamente quali identificatori appartengono all'oggetto "ambito" e quale non è , sono ** cattivi **, non usare quella sintassi in quelle lingue. In particolare, le modifiche future potrebbero modificare il comportamento di quel codice senza preavviso. Se quello non è un bug che aspetta solo di accadere, allora non so cosa sia. –

+1

Ad esempio, Visual Basic.NET ha capito bene, http://msdn.microsoft.com/en-us/library/wc500chb(VS.80).aspx, dove obbligano a prefixare tutti gli identificatori appartenenti all'oggetto ambito con un punto. –

+0

Sì, VB (.NET e prima) ha capito bene, ma hanno anche sbagliato: se usi l'associazione tardiva, hai ancora lo stesso problema. E la performance con 'with' è più lenta di allora (per qualche strana ragione). – Abel

5

vorrei evitare di utilizzarlo in codice di produzione perché è ambigua, ma c'è una soluzione alternativa per la soluzione per-loop-chiusura utilizzando with per imitare il let vincolante, ecco una copia della mia risposta precedente:

un'alternativa alla soluzione di chiusura standard utilizzando le funzioni all'interno di un ciclo for:

<a href="#">blah</a><br> 
<a href="#">blah</a><br> 
<a href="#">foo</a><br> 
<script> 
    (function() { 
    var anchors = document.getElementsByTagName('a'); 
     for (var i = anchors.length; i--;) { 
      var link = anchors[i]; 
      with ({ number: i }) { 
       link.onclick = function() { 
        alert(number); 
       }; 
      } 
     } 
    })(); 
</script> 

credito per nlogax per fornire un soluzione che ho praticamente strappato via: Javascript infamous Loop issue?

Ecco la soluzione standard:

<script> 
    (function() { 
    var anchors = document.getElementsByTagName('a'); 
    for (var i = anchors.length; i--;) { 
     var link = anchors[i]; 
     (function(i) { 
      link.onclick = function() { 
       alert(i) 
      } 
     })(i); 
    } 
    })(); 
</script> 
+2

Assicurati di indicare quale parte è "ambigua", poiché l'interprete JavaScript e/o il compilatore non sono mai confusi su cosa usare per identificatore. Sono le modifiche future e/o ciò che un programmatore potrebbe interpretare un identificatore in quanto questo è il problema. –

12

Nonostante consulenza al contrario un po 'ovunque, penso che ci sono usi per "con". Ad esempio, sto lavorando a un modello di dominio framework per Javascript, che usa il carattere di sottolineatura più o meno nello stesso modo in cui jQuery usa "$". Ciò significa che senza "with", ho molti underscore sparsi nel mio codice in modi che lo rendono meno leggibile. Ecco una riga a caso da un'applicazione utilizzando il framework:

_.People().sort(_.score(_.isa(_.Parent)),'Surname','Forename'); 

mentre con "con" sarebbe sembrare

with (_) { 
    ... 

    People().sort(score(isa(Parent)),'Surname','Forename'); 

    ... 
} 

Quale sarebbe veramente utile è una sola lettura versione di "con".

+0

Non sempre il runtime di SLOWER produce effetti collaterali. È trascurabile se non lo corri mille volte. – kroe

+2

In questi giorni, con la destrutturazione di oggetti ES6, si potrebbe invece fare 'const {People, score, isa, Parent} = _;', e non comportare tutti i rischi sgradevoli di 'with (_)'. –