Perché la chiusura è importante per JavaScript?


16

Anche l'espressione lambda di C # ha delle chiusure ma è raramente discussa dalle comunità o dai libri di C #. Vedo che molte più persone e libri JavaScript parlano delle sue chiusure di quanto non facciano nel mondo C #. Perché?


3
Perché JavaScript è trattato come un linguaggio funzionale di prima classe e C # è un linguaggio OOP classico. Diversi paradigmi, diversi stili di programmazione.
Raynos,

1
Avere una funzione di prima classe rende la lingua un linguaggio funzionale. PHP (dal 5.3), python o D ha una funzione di prima classe. Diresti che sono lingue funzionali? Certamente no, e neanche JavaScript.
deadalnix,

1
@deadalnix JavaScript è un linguaggio multi-paradigma. Supporta principalmente il paradigma OO procedurale, funzionale e prototipico. Non è affatto un linguaggio funzionale puro , ma puoi facilmente scrivere javascript nel paradigma funzionale senza piegare la lingua. Direi lo stesso di C # e Python.
Raynos,

3
@deadalnix, un linguaggio che consente di definire un Y-combinatore è un linguaggio funzionale. Per definizione.
SK-logic,

1
@deadalnix: suppongo che si tratti della domanda su quali approcci sono promossi dalla lingua. Esistono molti framework e piattaforme JavaScript (in particolare node.js e DOM (modello di eventi)) che si basano fortemente sulle funzioni del primo ordine. PHP ha le caratteristiche che consentono lo stesso stile di programmazione, ma se dai un'occhiata all'API standard o a molti framework, vedi che non è proprio al centro del linguaggio.
back2dos,

Risposte:


5

Perché JavaScript non ha funzionalità come gli spazi dei nomi e puoi fare confusione abbastanza facilmente con tutti i tipi di oggetti globali.

Quindi è importante essere in grado di isolare un po 'di codice nel proprio ambiente di esecuzione. La chiusura è perfetta per questo.

Questo uso della chiusura non ha senso in un linguaggio come C # in cui si hanno spazi dei nomi, classi e così via per isolare il codice e non mettere tutto nell'ambito globale.

Una pratica molto comune per il codice javascript è scrivere in questo modo:

(function(){
    // Some code
})();

Come puoi vedere, questa è una dichiarazione di funzione anonima, seguita immediatamente dalla sua esecuzione. Pertanto, è impossibile accedere a qualsiasi cosa definita all'interno della funzione dall'esterno e non confonderai l'ambito globale. Il contesto di esecuzione di questa funzione rimarrà in vita finché un codice lo utilizza, come le funzioni nidificate definite in questo contesto, che è possibile passare come callback o altro.

Javascript è un linguaggio molto diverso da C #. Non è orientato agli oggetti, è orientato ai prototipi. Questo porta a pratiche molto diverse alla fine.

Comunque, le chiusure sono buone, quindi usale, anche in C #!

EDIT: Dopo alcuni discorsi sulla chat di StackOverflow, penso che questa risposta debba essere precisa.

La funzione nel codice di esempio non è una chiusura. Tuttavia, questa fucntion può definire variabili locali e funzioni nidificate. Tutte le funzioni nidificate che utilizzano queste variabili locali sono chiusure.

Questo è utile per condividere alcuni dati tra una serie di funzioni senza incasinare l'ambito globale. Questo è l'uso più comune di chiusura in javascript.

La chiusura è molto più potente della semplice condivisione di alcuni dati come questo, ma siamo realistici, la maggior parte dei programmatori non sa nulla della programmazione funzionale. In C # avresti usato la classe o uno spazio dei nomi per questo tipo di utilizzo, ma JS non fornisce questa funzionalità.

Con la chiusura puoi fare molto di più che proteggere l'ambito globale, ma questo è ciò che vedrai nel codice sorgente di JS.


9
Non è una chiusura. Descrivi il vantaggio di usare le funzioni per creare un ambito locale.
Raynos,

2
una chiusura è solo una chiusura se si chiude su variabili libere. Grazie anche per avermi detto che non so come funziona JavaScript :)
Raynos,

2
piuttosto che ricorrere a indebolirmi chiamandomi un principiante, sentiti libero di avanzare argomenti concreti nella chat room SO JavaScript . Questa discussione non appartiene davvero qui, ma discuterò felicemente le tue idee sbagliate nella chat SO.
Raynos,

1
Downvoted. JavaScript è molto orientato agli oggetti. Non è solo basato sulla classe ma tale funzionalità è facilmente creabile. Ha funzioni di prima classe, sfrutta le chiusure per renderlo una misura naturale per i paradigmi fortemente guidati dagli eventi e una delle principali fonti di ispirazione secondo il suo autore, Brendan Eich, era Scheme. Non sono davvero sicuro di cosa pensi sia un linguaggio funzionale, ma la parte divertente è che sembra che l'ereditarietà basata sulla classe sia in qualche modo critica piuttosto che non del tutto necessaria quando puoi passare le funzioni e applicarle in nuovi contesti.
Erik Reppen,

2
-1 pure. Questo non descrive le chiusure, descrive l'ambito.
Izkata,

12

Probabilmente perché le implementazioni popolari dell'orientamento agli oggetti JavaScript dipendono dalle chiusure. Diamo un'occhiata a un semplice esempio:

function counter() {
   var value = 0;
   this.getValue = function() { return value; }
   this.increase = function() { value++; }
}

var myCounter = new counter();
console.log(myCounter.getValue());
myCounter.increase();
console.log(myCounter.getValue());

I metodi getValuee increasesono infatti chiusure, incapsulando la variabile value.


3
-1 "dipende dalle chiusure" È altamente soggettivo. Non è così.
Raynos,

Raynos: ti interessa mostrarci come creare e utilizzare membri privati ​​senza chiusure?
user281377

1
@ammoQ non esiste qualcosa come privato in JavaScript. Quello che intendevi era "perché l'emulazione OO classica di JavaScript dipende dalle chiusure". JavaScript OO è un prototipo che è un paradigma diverso. È una buona risposta alla domanda, "Usiamo le chiusure in JavaScript perché c'era bisogno di emulare OO classica"
Raynos,

1
@keppla intendevo che "OO dipende dalle chiusure" è soggettivo. Non hai bisogno di chiusure per OO.
Raynos,

2
mi stai esponendo come puttana rappresentante che sono ...
user281377

4

Perché molte delle librerie che rendono JavaScript "sopportabile" le usano.

Dai un'occhiata a JQuery , Prototype o MooTools , solo per citarne tre popolari. Ognuna di queste librerie fornisce un eachmetodo per le proprie raccolte come modo preferito di iterazione, che utilizza una funzione iteratore. Tale funzione, quando si accede ai valori nell'ambito esterno, sarà una chiusura:

[1,2,3].each(function(item) {
   console.log(item);
});

E non si ferma qui: i callback in Ajax, la gestione degli eventi in Ext.js, ecc. Prendono tutte le funzioni, e se non vuoi gonfiare il tuo codice con 100eds di funzioni che vengono chiamate esattamente una volta, le chiusure sono la strada da percorrere.


1
Perché non è una chiusura? console.logè definito in un ambito esterno, quindi consoleè una "variabile libera". E perché, in effetti, è un for-loop, che non fa nulla di diverso, una cattiva pratica?
keppla,

@Raynos: la mia definizione di chiusura è "blocco che contiene una variabile libera", non perde tale stato, la variabile libera risulta essere al top della portata. Ma, per sostenere il mio punto, considera questo metodo: pastie.org/2144689 . Perché questo dovrebbe essere negativo?
keppla,

Penso ancora che la "chiusura" sui dati globali sia considerata un imbroglio. Concordo sul fatto che l'accesso ai dati nella catena dell'ambito vada bene, è semplicemente una buona pratica minimizzare tale accesso.
Raynos,

Concordato di minimizzare l'accesso
keppla

Va notato che con gli iteratori di array (per ogni, mappa, riduzione, ecc.) Non vi è alcuna ragione per cui siano chiusure, hanno tutto lo stato passato direttamente in esse. Considererei un modello anti per loro essere chiusure
Raynos

3

Concordo con le altre risposte che la "buona" codifica con JavaScript dipende maggiormente dalle chiusure. Tuttavia, oltre a ciò, è probabilmente solo una questione di quanto tempo la funzionalità è in circolazione in ogni lingua. JavaScript ha praticamente chiuso chiusure sin dalle sue prime implementazioni. D'altra parte C # li ha solo dalla 3.0, che è stato rilasciato con Visual Studio 2008.

Molti programmatori C # in cui mi imbatto stanno ancora lavorando su progetti 2.0. E anche se funzionano in 3.0 o 4.0, spesso usano ancora i modi di dire 2.0. Adoro le chiusure; speriamo che vengano usati più pesantemente in C # mentre il concetto si propaga tra gli sviluppatori di C #.


2

Il motivo principale è perché C # è tipizzato staticamente e le funzioni hanno accesso solo a un unico ambiente predeterminato, che impedisce l'utilità delle chiusure.

In JavaScript, d'altra parte, le chiusure consentono alle funzioni di comportarsi come metodi quando si accede come proprietà di un oggetto ed essendo oggetti di prima classe, possono anche essere iniettate in diversi ambienti che consentono alle subroutine di operare in contesti diversi.


1
Cosa c'entra la tipizzazione statica con questo? Le chiusure sono ortogonali.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.