Consejos útiles

Plantilla de módulo Javascript

Un módulo es un archivo con un código.

En este archivo, la palabra clave exportar identifica variables y funciones que se pueden usar externamente.

Otros módulos pueden conectarlos a través de una llamada de importación.

La palabra clave de exportación se puede establecer:

  • antes de declarar variables, funciones y clases.
  • por separado, mientras que las llaves indican lo que se exporta.

Por ejemplo, la única variable se exporta de esta manera:

Puede escribir exportar por separado de la declaración:

En este caso, una o más variables exportadas se indican entre llaves.

Para dos variables será así:

El uso de la palabra clave as le permite especificar que la variable una será accesible externamente (exportada) bajo el nombre una vez, y dos bajo el nombre dos veces:

Exportar funciones y clases tiene el mismo aspecto:

Tenga en cuenta que tanto la función como la clase deben tener un nombre con esta exportación.

Entonces habrá un error:

Los nombres se especifican en la exportación, no las expresiones arbitrarias.

Otros módulos pueden incluir valores exportados utilizando la palabra clave import.

  • "./nums" - el módulo, como regla, esta es la ruta al archivo del módulo.
  • uno, dos: variables importadas que deben indicarse en números con la palabra exportar.

Como resultado de la importación, aparecerán una, dos variables locales, que contendrán los valores de las exportaciones correspondientes.

Por ejemplo, con este archivo nums.js:

El siguiente módulo generará "1 y 2":

Puede importar con un nombre diferente, especificándolo en "como":

Puede importar todos los valores a la vez como un objeto llamando a import * como obj, por ejemplo:

¿La estructura del 'módulo de plantilla'?

El módulo de plantilla incluye varias otras plantillas de JavaScript:

  • Declaración de dependencia
  • Espacio de nombres
  • Propiedades privadas y propiedades privilegiadas (métodos)
  • Función llamada instantáneamente (forma un ámbito local)

A continuación se presentan los conceptos básicos. plantilla javascript llamado 'el módulo'

¿Alguien puede explicar qué módulos son de nuevo?

Los buenos autores dividen sus libros en secciones y capítulos. Los buenos programadores dividen sus programas en módulos.

Al igual que los capítulos de un libro, los módulos son simplemente grupos de palabras (o código, según sea el caso).

Los buenos módulos tienen una funcionalidad autónoma, por lo que se pueden agregar, mover o eliminar según sea necesario sin romper todo el sistema.

¿Por qué usar módulos en absoluto?

De hecho, los módulos tienen muchas ventajas. Los más importantes, en mi opinión, son los siguientes:

  1. Soporte conveniente (mantenibilidad): Por definición, un módulo es autónomo. Un módulo bien diseñado está diseñado para reducir las dependencias de partes de su base de código tanto como sea posible para que pueda crecer y mejorar de forma independiente el uno del otro. Actualizar un módulo es mucho más fácil cuando está separado de otras partes del código. Regresando a nuestro libro, por ejemplo, si desea hacer un pequeño cambio en un capítulo y esto implicará cambios en alguna otra sección de su libro, esto será una pesadilla. Por lo tanto, el capítulo debe estar escrito de modo que, al realizar cambios, no sea necesario tocar otros capítulos.
  2. Espacio de nombres: En JavaScript, las variables que están fuera de las funciones de nivel superior se consideran globales (todos pueden acceder a ellas). Por lo tanto, es muy común la "contaminación del espacio de nombres", donde el código completamente no relacionado, las variables globales se unen. El uso conjunto de variables globales en el código que no está interconectado muy mal en el desarrollo. Más adelante en este artículo veremos que Los módulos nos permiten evitar la contaminación del espacio de nombres global creando espacios privados para nuestras variables.
  3. Reusabilidad: Seamos honestos. Todos copiamos el código en nuevos proyectos que escribimos antes. Por ejemplo, supongamos que copió algunos métodos auxiliares de un proyecto anterior en un proyecto nuevo. Bueno, pero si encuentra la mejor manera de escribir esta parte, tendrá que recordar todos los lugares donde apareció este código para actualizarlo. Esto es ciertamente una gran pérdida de tiempo. Sería mucho más fácil escribir un módulo y reutilizarlo una y otra vez.

Patrón del módulo

El patrón "Módulo" se usa para simular el concepto de clases (dado que JavaScript no admitía clases inicialmente), por lo que podemos almacenar métodos (variables) públicos y privados dentro de un objeto, como se hace en clases de otros lenguajes, como Java o Python. Esto nos permite crear una API pública y proporcionar la capacidad de acceder a métodos públicos, mientras que las variables y métodos privados se encapsulan en un cierre.

Hay varias formas de implementar el patrón "Módulo". En el primer ejemplo, usaré cierres anónimos. Poner el código en una función anónima nos ayudará a lograr nuestro objetivo. (Recuerde que en JavaScript, las funciones son la única forma de crear un nuevo ámbito).

Ejemplo 1: cierres anónimos

Por lo tanto, nuestra función anónima tiene su propio alcance o "cierre" y podemos ejecutarla de inmediato. Este método nos permite ocultar variables del ámbito primario (global).

Lo realmente bueno de este enfoque es que puede usar variables locales dentro de esta función y no tener miedo de sobrescribir accidentalmente variables globales con el mismo nombre. Pero aún tiene acceso a variables globales, por ejemplo, así:

Tenga en cuenta que se requieren paréntesis alrededor de una función anónima, porque una instrucción que comienza con una palabra clave funcion siempre se consideró una declaración de función (recuerde que en JavaScript no puede declarar funciones sin un nombre). Por lo tanto, los paréntesis que rodean la declaración invocan la función en lugar de declararla. Si está interesado, puede leer más aquí.

Ejemplo 2: Importación global

Otro enfoque popular que usan las bibliotecas como jQuery es la importación global. Es similar a los cierres que acabamos de ver, solo que ahora estamos pasando variables globales como parámetros.

En este ejemplo, GlobalVariable es la única variable global. La ventaja de este enfoque es que declara todas las variables globales por adelantado, lo que hace que su código sea transparente para el resto.

Ejemplo 3: interfaz de objeto

Otro enfoque para crear módulos es utilizar interfaces de objeto autónomas, por ejemplo, así:

Como habrás notado, este enfoque te permite decidir qué variables (métodos) queremos que sean privadas (por ejemplo, myGrades), y cuáles públicos los colocaron en el objeto devuelto (por ejemplo, promedio y fallando).

Ejemplo 4: Patrón de módulo desplegable

Este ejemplo es muy similar al anterior, excepto que todos los métodos y variables permanecen privados hasta que se abren explícitamente.

Esto puede parecer una gran cantidad de información, pero esto es solo la punta del iceberg cuando se trata de patrones de módulos. Aquí hay algunos recursos útiles que encontré mientras realizaba mi investigación:

  • Aprender patrones de diseño de JavaScript por Addy Osmani: este es un tesoro de detalles y contenido expresamente conciso.
  • Adecuately Good de Ben Cherry: una descripción general útil con ejemplos de uso avanzado del patrón "Módulo",
  • Blog de Carl Danley: una descripción general del patrón de módulo y recursos para otros patrones de JavaScript,

CommonJS y AMD

Todos los enfoques anteriores tienen una propiedad común: todos crean una variable global en la que colocan el código de función, creando así un espacio de nombres privado y utilizando el alcance del cierre.

Aunque cada uno de estos enfoques es efectivo a su manera, también tienen sus inconvenientes.

Usted como desarrollador debe conocer el orden correcto de carga de archivos. Por ejemplo, suponga que usa Backbone en su proyecto, por lo que incluye el script Backbone a través de la etiqueta en su archivo. Dado que Backbone depende directamente de Underscore.js, no puede incluir el script Backbone.js delante de Underscore.js.

La gestión de la dependencia del desarrollador a veces es un dolor de cabeza.

Otro inconveniente es que los conflictos de espacio de nombres aún pueden ocurrir. Por ejemplo, puede tener dos módulos con el mismo nombre o dos versiones del mismo módulo y necesita ambos.

En base a esto, surge una pregunta interesante: ¿podemos acceder a la interfaz del módulo no a través del alcance global?

Afortunadamente, la respuesta es sí.

Js nativos

Fuuuh ¿Sigues cerca? ¿No te he perdido en este bosque? Bueno! Porque tenemos otro tipo de definición de módulo.

Como puede ver arriba, ninguno de los módulos era nativo de JavaScript. En cambio, imitamos un sistema de módulos usando el patrón "Módulo", o CommonJS, o AMD.

Afortunadamente, las personas inteligentes de TC39 (el organismo de estándares que define la sintaxis y la semántica de ECMAScript) han agregado módulos integrados en ECMAScript 6 (ES6).

ES6 ofrece una variedad de opciones para importar y exportar módulos de los que se ha hablado más de una vez. Aquí hay un par de recursos:

¿Qué tiene de bueno los módulos ES6 en comparación con CommonJS y AMD? Que reunió lo mejor de dos mundos: compacidad, sintaxis declarativa, carga asincrónica, además de beneficios adicionales como dependencias circulares.

Probablemente mi característica favorita de los módulos ES6 es que las importaciones son tipos de exportaciones de solo lectura en vivo (en comparación con CommonJS, donde la importación es solo una copia de la exportación).

Aquí hay un ejemplo de cómo funciona esto:

En este ejemplo, hicimos dos copias del módulo base: la primera vez que lo exportamos y la segunda cuando lo importamos.

Además, una copia que se encuentra en main.js ahora desconectado del módulo original. Por lo tanto, incluso cuando aumentamos nuestro contador, aún devuelve 1, ya que contador es una variable que importamos del módulo, desconectada del módulo original.

Por lo tanto, aumentar el contador lo aumentará en el módulo, pero no aumentará en la versión copiada. La única forma de cambiar la versión copiada es aumentarla manualmente:

Y, cuando se importa, ES6 crea una vista en vivo de solo lectura del módulo:

Interesante, ¿no es así? Lo que encuentro realmente convincente en las vistas en vivo de solo lectura es que le permiten dividir sus módulos en partes más pequeñas sin perder la funcionalidad.

Puede implementarlos y combinarlos nuevamente (en un nuevo proyecto), y no hay problema. Todo funcionará

Mirando un poco hacia adelante: ensamblando módulos

Wow! Qué rápido pasó el tiempo. Fue un gran viaje y sinceramente espero que el artículo te haya dado la oportunidad de comprender mejor los módulos en JavaScript.

En el próximo artículo consideraremos el enlace del módulo, cubriremos los temas principales, que incluyen:

  • ¿Por qué recopilamos módulos?
  • Diferentes enfoques de montaje,
  • API del cargador del módulo ECMAScript,
  • Y mucho mas.

exportación por defecto

Vimos anteriormente que un módulo puede exportar variables seleccionadas con exportar.

Sin embargo, como regla, intentan organizar el código para que cada módulo haga una cosa. En otras palabras, "un archivo es una entidad que describe". Por ejemplo, el archivo user.js contiene la clase Usuario, el archivo login.js contiene la función login () para autorización, etc.

En este caso, los módulos, por supuesto, se usarán entre sí. Por ejemplo, login.js probablemente importará la clase Usuario desde el módulo user.js.

Para esta situación, cuando un módulo exporta un valor único, se proporciona un valor predeterminado de exportación de combinación de teclas especial.

Si coloca la palabra predeterminada después de la exportación, el valor se convertirá en "exportación predeterminada".

Este valor se puede importar sin llaves.

Por ejemplo, el archivo user.js:

... Y en el archivo login.js:

"Exportar por defecto" es un tipo de "azúcar sintáctico". Sin él, sería posible importar el valor de la forma habitual a través de llaves <...>. Si user.js no tuviera un valor predeterminado, entonces las llaves deberían especificarse en login.js:

En la práctica, este "azúcar" es muy agradable, ya que facilita ver qué valor exporta el módulo, así como prescindir de caracteres adicionales al importar.

Plantilla de módulo

Una función llamada inmediatamente forma un ámbito local en el que puede declarar las propiedades y métodos privados necesarios. El resultado de la función es un objeto que contiene propiedades y métodos públicos.

Al pasar parámetros a una función llamada inmediatamente, puede importar dependencias en el módulo. Esto aumenta la velocidad de resolución de variables, ya que los valores importados se convierten en variables locales dentro de la función.

Formatos de módulos

Desde un punto de vista estructural, el módulo CommonJS es parte del código JavaScript que exporta ciertas variables, objetos o funciones, haciéndolos disponibles para cualquier código dependiente.

Los módulos CommonJS constan de dos partes: module.exports contiene objetos que el módulo desea poner a disposición, y la función require () se usa para importar otros módulos.

Módulo de ejemplo en formato CommonJS:

Código de ejemplo usando el módulo:

El formato AMD (Asynchronous Module Definition) se basa en dos funciones: define () para definir módulos con nombre o sin nombre y require () para importar dependencias.

La función define () tiene la siguiente firma:

El parámetro module_id es opcional; por lo general, solo se requiere cuando se utilizan herramientas de fusión que no son AMD. Cuando se omite este argumento, el módulo se llama anónimo. El parámetro de dependencias es una matriz de dependencias que requiere el módulo definido, y el tercer argumento (función de definición) es la función que se ejecuta para crear la instancia del módulo.

La función require () se usa para importar módulos:

Además, con require (), puede importar dinámicamente dependencias en un módulo:

La existencia de dos formatos de módulos incompatibles entre sí no contribuyó al desarrollo del ecosistema de JavaScript. Para resolver este problema, se desarrolló el formato UMD (Universal Module Definition). Este formato le permite usar el mismo módulo con herramientas AMD y entornos CommonJS.

La esencia del enfoque UMD es verificar el soporte de un formato particular y declarar el módulo en consecuencia. Un ejemplo de tal implementación:

UMD es un enfoque más que un formato específico. Puede haber muchas implementaciones diferentes.

Módulos ECMAScript 2015

ECMAScript 2015 introdujo módulos JavaScript nativos. Actualmente, los módulos ES6 son compatibles con Safari 10.1 y más allá del indicador en Firefox 54, Chrome 60 y Edge 15.

Los módulos ES6 se basan en las palabras clave exportar e importar. Solo se puede acceder a cualquier variable declarada en el módulo si se exporta explícitamente desde el módulo.

Si el módulo exporta solo un valor, puede usar la exportación predeterminada. Por ejemplo, un módulo exporta una función:

O incluso la expresión:

Un módulo puede exportar múltiples valores:

Puede enumerar todo lo que desea exportar al final del módulo:

También puede importar módulos de varias maneras:

Las palabras clave de importación y exportación solo se pueden usar en el nivel superior., no se pueden usar en una función o en un bloque:

La importación desde el módulo se eleva al comienzo del alcance:

Los módulos ES6 se ejecutan diferidos solo cuando el documento se analiza completamente.

El código del módulo se ejecuta en modo estricto.

Cargadores de módulos

AMD y CommonJS son formatos de módulo, no implementaciones. Para el soporte de AMD, por ejemplo, se requiere una implementación de las funciones define () y require (); para el soporte de CommonJS, se requiere una implementación de module.exports y require ().

Para admitir módulos en tiempo de ejecución, se utilizan cargadores de módulos. Hay varios gestores de arranque diferentes, tienen un principio de funcionamiento similar:

  • Conecta el script del gestor de arranque en el navegador y le dice qué archivo cargar como el principal.
  • El cargador de módulos carga el archivo principal de la aplicación.
  • El cargador de módulos descarga los archivos restantes según sea necesario.

Cargadores de módulos populares:

  • RequireJS carga módulos en formato AMD.
  • curl.js carga los módulos AMD y CommonJS.
  • SystemJS carga los módulos AMD y CommonJS.

Constructores de módulos

A diferencia de los cargadores de módulos, que funcionan en el navegador y cargan dependencias sobre la marcha, los constructores de módulos le permiten preparar previamente un archivo con todas las dependencias (paquete).

Hay una serie de herramientas que le permiten premontar módulos en un solo archivo:

  • Browserify admite el formato CommonJS.
  • Webpack admite módulos AMD, CommonJS y ES6.
  • Rollup admite módulos ES6.

Conclusión

Para navegar mejor por las herramientas de desarrollo front-end modernas, debe comprender conceptos como módulos, formatos de módulos, cargadores de módulos y constructores.

Modulo Es un código reutilizable que encapsula los detalles de implementación y proporciona una API abierta.

Formato del módulo Es la sintaxis para definir y conectar un módulo.

Cargador de módulos carga un módulo de un formato específico en tiempo de ejecución directamente en el navegador. Los cargadores de arranque populares son RequireJS y SystemJS.

Constructor de módulos combina los módulos de antemano en un archivo, que está conectado en la página. Ejemplos de coleccionistas son Webpack y Browserify.

El primer uso de este enfoque se notó en 2003, cuando Richard Kornford lo citó como un ejemplo del uso de cierres.

En 2005-2006, los desarrolladores de YUI utilizaron este enfoque para su marco.

La plantilla más popular fue el módulo después de que Douglas Crockford lo describiera en su libro JavaScript the Good Part.

В 2009 году сотрудник Mozilla Кевин Дангур опубликовал сообщение с призывом присоединиться к неофициальному комитету для обсуждения и разработки серверного JavaScript API, который назывался ServerJS.

Полгода спустя ServerJS был переименован в CommonJS. Наибольшее внимание было уделено спецификации модулей, которые в конечном итоге были реализованы в Node.JS.

Во время работы над спецификацией CommonJS обсуждалась возможность асинхронной загрузки модулей. Другой разработчик из Mozilla Джеймс Берк предложил свой формат, который назывался AMD (Asynchronous Module Definition).

В 2011 году Джеймс объявил о создании отдельного списка рассылки для координации всех работ над AMD, т.к. консенсус с группой CommonJS за все это время не был достигнут.

Впервые такой подход использовали Джеймс Берк и Крис Ковал при разработке библиотеки Q, а Эдди Османи собрал похожие шаблоны в одном репозитории и назвал UMD

El trabajo en el sistema de módulos comenzó en 2010. El desarrollador principal de esta especificación fue Dave Herman, director de desarrollo estratégico de Mozilla.

¿Encontraste un error tipográfico? Orphus: Ctrl + Enter

© getinstance.info Todos los derechos reservados. 2014-2018

Todos los derechos sobre los materiales publicados en este sitio pertenecen al personal editorial del sitio, con la excepción de los casos de reimpresión de materiales de otras personas, y están protegidos de acuerdo con la legislación de la Federación Rusa.

Módulo de plantilla a través de la función constructora

El módulo módulo también se puede utilizar para diseñadores. Usando constructores es mucho más conveniente crear instancias de una "clase". A diferencia del "módulo de plantilla" estándar, en el caso de un constructor, se devuelve una función, no un objeto.

Escalada

Una de las limitaciones de la plantilla del módulo es que todo el código del módulo debe estar en un archivo. Sin embargo, aquellos que han trabajado en un proyecto grande comprenden la importancia de dividir el código en múltiples archivos. Afortunadamente, tenemos una buena solución para expandir el módulo. Primero importamos el módulo, luego agregamos las propiedades, luego exportamos el módulo. Aquí hay un ejemplo que extiende nuestro MÓDULO:

Acumulación comprimida / ordenada

La construcción libre es buena, pero impone algunas limitaciones. Lo más importante, no puede cambiar las propiedades de un módulo de forma segura. Tampoco puede usar las propiedades del módulo de otros archivos durante la inicialización (pero es posible después de que se complete la inicialización). Una extensión comprimida implica un orden de arranque, pero permite la anulación. A continuación se muestra un ejemplo (ampliando nuestro módulo original)

Aquí redefinimos MODULE.moduleMethod, pero mantenemos una referencia al método original, si es necesario.

Clonación y Herencia

Esta plantilla es quizás la menos flexible. Proporciona algunos beneficios, pero esto tiene el costo de la flexibilidad. Las propiedades que son objetos o funciones no están duplicadas; existirán como un solo objeto con dos referencias. Al cambiar uno, el otro cambiará. Esto puede arreglarse para objetos que usan recursividad durante el proceso de clonación, pero puede no arreglarse para funciones, excepto posiblemente con eval. Sin embargo, lo he incluido para completar.

Módulos Commonjs (module.exports)

Cuando conectamos un módulo usando require, el complemento se conecta solo una vez. El uso requiere al menos 10 veces, el módulo se conectará 1 vez (el código se toma del caché).

Cuando trabajamos con módulos, por regla general, todo se "vierte" en un solo archivo para que el navegador entienda qué conectar / usar.

"Cuando conectamos el módulo a través de require, el módulo solo se conecta una vez". (los datos se toman del caché) Es decir, recordamos la función del módulo con un cierre. En otras palabras, la variable de contador se almacena en un cierre que ya ha sido reemplazado.

Puedes usar el concepto de SINGLTON. Singleton es un objeto (entidad) que se crea solo una vez y no hay forma de crearlo por segunda vez. De hecho, nuestro módulo es el mismo singleton.

Qué salida no cierra las variables, etc. al módulo:

1. Esta es una función de exportación que devuelve otra función:

A continuación se muestra un módulo de plantilla que encapsula datos.

Los módulos no se crean para conectarlos muchas veces. Solo necesita exportar correctamente algo del módulo. También puede usar los valores predeterminados:

Qué salida no cierra las variables, etc. al módulo: