Care este diferența în stilul de închidere

Există două stiluri populare de închidere în javascript. Primul pe care îl numesc constructorul anonim :

new function() { 
  var code...
}

și funcția executată în linie :

(function() {
  var code...
})();

există diferențe de comportament între cele două? Este unul "mai bun" decât celălalt?

0
fr hi bn

6 răspunsuri

Da, există diferențe între cele două.

Ambele sunt funcții anonime și se execută în același mod. Dar, diferența dintre cele două este că în al doilea caz domeniul de aplicare al variabilelor este limitat la funcția anonimă în sine. Nu există nicio șansă de adăugare accidentală a variabilelor în domeniul global.

Acest lucru implică faptul că prin utilizarea celei de-a doua metode, nu depășiți domeniul variabilelor globale, lucru bun, deoarece aceste valori ale variabilelor globale pot interfera cu alte variabile globale pe care le puteți utiliza în altă bibliotecă sau care sunt utilizate într-o bibliotecă terță parte .

Exemplu:

<html>
<body>
<script type="text/javascript">

new function() { 
a = "Hello";
alert(a + " Inside Function");
};

alert(a + " Outside Function");

(function() { 
var b = "World";
alert(b + " Inside Function");
})();

alert(b + " Outside Function");
</script>
</body>
</html>

În codul de mai sus, ieșirea este ceva de genul:

Hello Inside Function   Hello Outside Funcția   Funcția World Inside

... atunci veți obține o eroare deoarece "b" nu este definită în afara funcției!

Astfel, cred că a doua metodă este mai bună ... mai sigură!

0
adăugat
-1 Aceasta se datorează faptului că omite "var" înainte de "a" făcându-l global și nu are nicio legătură cu întrebarea.
adăugat autor Tomas, sursa

Al doilea exemplu va executa funcția după ce a fost creată.

editați: acest lucru nu este cu adevărat adevărat.

0
adăugat

Am făcut o pagină ca aceasta:

<html>
<body>
<script type="text/javascript">
var a = new function() { 
  alert("method 1");

  return "test";
};

var b = (function() {
  alert("method 2");

  return "test";
})();

alert(a);  //a is a function
alert(b);  //b is a string containing "test"

</script>
</body>
</html>

În mod surprinzător (pentru mine oricum) a alertat atât "metoda 1", cât și metoda 2. "Nu m-am așteptat ca" metoda 1 "să fie alertă, diferența fiind ceea ce valorile a și b erau. în timp ce b a fost șirul pe care funcția a revenit.

0
adăugat

Ambele realizează o închidere prin executarea blocului de coduri. Ca o chestiune de stil, prefer cel de-al doilea din câteva motive:

Nu este evident imediat prin priviri la prima vedere că codul va fi executat efectiv; linia arata ca este crearea o noua functie, mai degraba decat executarea ei ca constructor, dar asta nu se intampla. Evitați codul care nu face ceea ce pare să facă!

De asemenea, (funcția() { ... }) (); face token-uri de rezervă frumoase, astfel încât să puteți observa imediat că intrați și părăsiți domeniul de închidere. Acest lucru este bun pentru că îl avertizează pe cel care îl citește la schimbarea domeniului de aplicare și este util în special dacă efectuați o postprocesare a fișierului, de exemplu pentru minificare.

0
adăugat

@Lance: prima este de asemenea executată. Comparați-l cu un constructor numit:

function Blah() {
    alert('blah');
}
new Bla();

acest lucru este de fapt, de asemenea, de executare a codului. Același lucru este valabil și pentru constructorul anonim ...

Dar asta nu era întrebarea ;-)

0
adăugat

Ambele cazuri vor executa funcția, singura diferență reală este cea a valorii returnate a expresiei și care va fi valoarea "acestui" în interiorul funcției.

Comportamentul principal al

new expression

Este efectiv echivalent cu

var tempObject = {};
var result = expression.call(tempObject);
if (result is not an object)
    result = tempObject;

Deși, desigur, tempObject și rezultatul sunt valori tranzitorii pe care nu le puteți vedea niciodată (ele sunt detalii de implementare în interpret) și nu există niciun mecanism JS care să facă verificarea "nu este un obiect".

În general, metoda "new function() {..}" va fi mai lentă datorită necesității de a crea acest obiect pentru constructor.

Asta a spus că aceasta nu ar trebui să fie o diferență reală, deoarece alocarea obiectelor nu este lentă și nu ar trebui să utilizați un astfel de cod în codul fierbinte (datorită costului creării obiectului de funcție și a închiderii asociate).

Edit: one thing i realised that i missed from this is that the tempObject will get expressions prototype, eg. (before the expression.call) tempObject.__proto__ = expression.prototype

0
adăugat
JavaScript, România - Moldova
JavaScript, România - Moldova
328 participanți

Comunitatea Română JavaScript: github.com/js-ro Pentru confort, opriți notificările. Parteneri: @node_ro, @php_ro, @python_ro, @seo_ro, @RomaniaGroup, @ai_ro, @Grupuri_IT Offtop: @holywars_ro Joburi: @js_jobs_ro Sponsored with ❤️ by ciupacabra.com