¿Por qué es importante el cierre para JavaScript?

16

La expresión lambda de C # también tiene cierres, pero rara vez es discutida por las comunidades o libros de C #. Veo que muchas más personas y libros de JavaScript hablan sobre sus cierres que en el mundo de C #. ¿Porqué es eso?

TomCaps
fuente
3
Debido a que JavaScript se trata como un lenguaje funcional de primera clase y C # es un lenguaje OOP clásico. Diferentes paradigmas, diferentes estilos de programación.
Raynos
1
Tener una función de primera clase hace que el lenguaje sea un lenguaje funcional. PHP (desde 5.3), python o D tiene una función de primera clase. ¿Dirías que son lenguajes funcionales? Ciertamente no, y javascript tampoco.
deadalnix
1
@deadalnix JavaScript es un lenguaje de paradigmas múltiples. Admite principalmente el paradigma de OO de procedimiento, funcional y prototípico. De ninguna manera es un lenguaje funcional puro , pero puede escribir fácilmente javascript en el paradigma funcional sin doblar el idioma. Yo diría lo mismo de C # y Python.
Raynos
3
@deadalnix, un lenguaje que le permite definir un combinador Y es un lenguaje funcional. Por definición.
SK-logic
1
@deadalnix: Supongo que todo se reduce a la pregunta de qué enfoques promueve el lenguaje. Hay muchos marcos y plataformas de JavaScript (especialmente node.js y DOM (modelo de evento)) que dependen en gran medida de las funciones de primer orden. PHP tiene las características que permiten el mismo estilo de programación, pero si echa un vistazo a la API estándar o a muchos marcos, verá que no es realmente el núcleo del lenguaje.
back2dos

Respuestas:

5

Debido a que JavaScript no tiene características como los espacios de nombres, y puede desordenar fácilmente con todo tipo de objetos globales.

Por lo tanto, es importante poder aislar algún código en su propio entorno de ejecución. Los cierres son perfectos para eso.

Este uso del cierre no tiene sentido en un lenguaje como C # donde tiene espacios de nombres, clases, etc. para aislar el código y no poner todo en el ámbito global.

Una práctica muy común para el código javascript es escribirlo así:

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

Como puede ver, esta es una declaración de función anónima, seguida inmediatamente por su ejecución. Por lo tanto, es imposible acceder a todo lo definido dentro de la función desde el exterior, y no arruinará el alcance global. El contexto de ejecución de esta función permanecerá activo mientras algún código lo use, como funciones anidadas definidas dentro de este contexto, que puede pasar como devolución de llamada o lo que sea.

Javascript es un lenguaje muy diferente a C #. No está orientado a objetos, está orientado a prototipos. Esto lleva a prácticas muy diferentes al final.

De todos modos, los cierres son buenos, ¡así que úsalos, incluso en C #!

EDITAR: Después de discutir sobre el chat de stackoverflow, creo que esta respuesta debe ser precisa.

La función en el código de muestra no es un cierre. Sin embargo, esta función puede definir variables locales y funciones anidadas. Todas las funciones anidadas que usan estas variables locales son cierres.

Esto es útil para compartir algunos datos a través de un conjunto de funciones sin alterar el alcance global. Este es el uso más común de cierre en javascript.

Los cierres son mucho más poderosos que simplemente compartir algunos datos como este, pero seamos realistas, la mayoría de los programadores no saben nada sobre programación funcional. En C #, habría utilizado una clase o un espacio de nombres para este tipo de uso, pero JS no proporciona esta funcionalidad.

Con el cierre, puede hacer mucho más que solo proteger el alcance global, pero esto es lo que verá en el código fuente de JS.

deadalnix
fuente
9
Eso no es un cierre. Usted describe la ventaja de usar funciones para crear un alcance local.
Raynos
2
un cierre es solo un cierre si se cierra sobre variables libres. También gracias por decirme que no sé cómo funciona JavaScript :)
Raynos
2
en lugar de recurrir a socavarme llamándome principiante, siéntase libre de presentar argumentos reales en la sala de chat JavaScript SO . Esta discusión realmente no pertenece aquí, pero felizmente discutiré tus ideas falsas en el chat SO.
Raynos
1
Voto negativo JavaScript está bastante orientado a objetos. Simplemente no está basado en clases, pero dicha funcionalidad se crea fácilmente. Tiene funciones de primera clase, aprovecha los cierres para que sea un ajuste natural para paradigmas fuertemente impulsados ​​por eventos, y una fuente principal de inspiración según su autor, Brendan Eich, fue Scheme. No estoy realmente seguro de qué crees que es un lenguaje funcional, pero la parte divertida es que pareces pensar que la herencia basada en clases es de alguna manera crítica en lugar de ya no es completamente necesaria cuando puedes pasar funciones y aplicarlas en nuevos contextos.
Erik Reppen
2
-1 también. Esto no describe los cierres, describe el alcance.
Izkata
12

Probablemente porque las implementaciones populares de la orientación a objetos de JavaScript dependen de los cierres. Veamos un ejemplo simple:

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());

Los métodos getValuey increasede hecho son cierres, encapsulando la variable value.

usuario281377
fuente
3
-1 "depende de cierres" Eso es muy subjetivo. No es asi.
Raynos
Raynos: ¿te gustaría mostrarnos cómo crear y usar miembros privados sin cierres?
user281377
1
@ammoQ no hay nada privado en JavaScript. Lo que quisiste decir fue "porque la emulación OO clásica de JavaScript depende de los cierres". JavaScript OO es prototípico, que es un paradigma diferente. Sin embargo, es una buena respuesta a la pregunta: "Utilizamos cierres en JavaScript porque era necesario emular la OO clásica"
Raynos
1
@keppla Quise decir "OO depende de los cierres" es subjetivo. No necesita cierres para OO en absoluto.
Raynos
2
me estás exponiendo como el representante de puta que soy ...
user281377
4

Porque muchas de las bibliotecas que hacen que JavaScript sea soportable los usan.

Eche un vistazo a JQuery , Prototype o MooTools , solo por nombrar tres populares. Cada una de esas bibliotecas proporciona un eachmétodo para sus colecciones como la forma preferida de iteración, que utiliza una función de iterador. Esa función, al acceder a valores en el ámbito externo, será un cierre:

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

Y no se detiene allí: las devoluciones de llamada en Ajax, el manejo de eventos en Ext.js, etc.todas toman funciones, y si no desea inflar su código con 100eds de funciones que se llaman exactamente una vez, los cierres son el camino a seguir.

keppla
fuente
1
¿Por qué no es un cierre? console.logse define en un ámbito externo, por lo que consolees una 'variable libre'. Y, ¿por qué es, en efecto, un bucle for, que no hace nada diferente, una mala práctica?
keppla
@Raynos: mi definición de cierre es 'bloque que contiene una variable libre', no pierde ese estado, si la variable libre está en el alcance superior. Pero, para apoyar mi punto, considere este método: pastie.org/2144689 . ¿Por qué debería ser esto malo?
keppla
Todavía creo que "cerrar" los datos globales se considera una trampa. Estoy de acuerdo en que acceder a los datos en la cadena de alcance está bien, es simplemente una buena práctica minimizar ese acceso.
Raynos
Acordado en minimizar el acceso
keppla
Cabe señalar que con los iteradores de matriz (para Cada, mapear, reducir, etc.) no hay ninguna razón para que sean cierres, tienen todo el estado pasado directamente a ellos. Yo consideraría un anti patrón para ellos ser cierres
Raynos
3

Estoy de acuerdo con las otras respuestas de que la codificación "buena" con JavaScript depende más de los cierres. Sin embargo, además de eso, probablemente solo se trate de cuánto tiempo ha estado presente la función en cada idioma. JavaScript ha tenido básicamente cierres desde sus primeras implementaciones. C # por otro lado solo los ha tenido desde 3.0, que se lanzó con Visual Studio 2008.

Muchos programadores de C # con los que me encuentro todavía están trabajando en proyectos 2.0. E incluso si están trabajando en 3.0 o 4.0, a menudo todavía usan modismos 2.0. Amo los cierres; con suerte, se utilizarán más en C # a medida que el concepto se propague entre los desarrolladores de C #.

RationalGeek
fuente
2

La razón principal es que C # está estáticamente tipado y las funciones solo tienen acceso a un entorno único predeterminado, lo que impide la utilidad de los cierres.

En JavaScript, por otro lado, los cierres permiten que las funciones se comporten como métodos cuando se accede como una propiedad de objeto y como objetos de primera clase, también se pueden inyectar en diferentes entornos que permiten que las subrutinas operen en diferentes contextos.

Filip Dupanović
fuente
1
¿Qué tiene que ver la escritura estática con esto? Los cierres son ortogonales.