[ES6] Módulo de aprendizaje Ruan Yifeng ES6 Gramática

1. Introducción

Antes de ES6, había principalmente dos tipos de CommonJSy AMD. CommonJS para el servidor, AMD para el navegador. ES6 implementa funciones de módulo a nivel de estándares de lenguaje, y la implementación es bastante simple.Puede reemplazar completamente las especificaciones de CommonJS y AMD y convertirse en una solución de módulo común para navegadores y servidores. Entró en la gran etapa de unificación.

La idea de diseño de los módulos ES6 es ser lo más estáticos posible, haciendotiempo de compilaciónPuede determinar las dependencias del módulo, así como las variables de entrada y salida. Los módulos CommonJS y AMD solo se pueden usar entiempo de ejecuciónAsegúrate de estas cosas.

// CommonJS模块
let {
    
     stat, exists, readfile } = require('fs');

// 等同于
let _fs = require('fs');
let stat = _fs.stat;
let exists = _fs.exists;
let readfile = _fs.readfile;

Este tipo de carga se denomina "carga en tiempo de ejecución", porque este objeto solo se puede obtener en tiempo de ejecución, por lo que no se puede realizar una "optimización estática" en tiempo de compilación.

exportLos módulos ES6 no son objetos, sino códigos que especifican explícitamente la salida a través de comandos y luego importla entrada a través de comandos.

// ES6模块
import {
    
     stat, exists, readFile } from 'fs';

La esencia del código anterior es cargar 3 métodos desde el módulo fs, y otros métodos no se cargan. Esta carga se denomina "carga en tiempo de compilación" o carga estática. Es decir, ES6 puede completar la carga del módulo en tiempo de compilación, lo que es más eficiente que la carga del módulo CommonJS. Por supuesto, esto también hace que sea imposible hacer referencia al propio módulo ES6, ya que no es un objeto.

2. Modo estricto

Los módulos ES6 adoptan automáticamente el modo estricto, ya sea que lo agregue al encabezado del módulo o no "use strict".

El modo estricto tiene principalmente las siguientes restricciones.

  • Las variables deben declararse antes de que puedan usarse
  • Los parámetros de la función no pueden tener atributos con el mismo nombre, de lo contrario se reportará un error
  • no se puede usar la sentencia with
  • No puede asignar un valor a un atributo de solo lectura; de lo contrario, se informará un error
  • Los atributos que no se pueden eliminar no se pueden eliminar; de lo contrario, se informará un error
  • Las variables no se pueden eliminar delete prop, se informará un error, solo se pueden eliminar los atributosdelete global[prop]
  • evalNo introduce variables en su ámbito exterior.
  • evaly argumentsno se puede reasignar
  • argumentsNo refleja automáticamente los cambios en los parámetros de la función
  • Fuera de servicioarguments.callee
  • Fuera de servicioarguments.caller
  • No thisapuntes al objeto global.
  • No se puede usar fn.callery fn.argumentsobtener la pila de una llamada de función
  • Se agregaron palabras reservadas (como protected, staticy interface)

3. comando de exportación

La función del módulo consta principalmente de dos comandos: exporty import. exportEl comando se usa para especificar la interfaz externa del módulo, y importel comando se usa para ingresar las funciones proporcionadas por otros módulos.

Un módulo es un solo archivo. Todas las variables dentro del archivo no se pueden obtener desde el exterior. Si desea que el exterior pueda leer una variable dentro del módulo, debe usar exportla palabra clave para generar la variable. A continuación se muestra un archivo JS que utiliza exportvariables de salida de comandos.

// profile.js
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;

// 另一种写法
// profile.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;

export {
    
     firstName, lastName, year };

exportAdemás de generar variables, los comandos también pueden generar funciones o clases.

export function multiply(x, y) {
    
    
  return x * y;
};

El código anterior genera una función externamente multiply.

Normalmente, exportla variable de salida es el nombre original, pero se puede asrenombrar usando palabras clave.

function v1() {
    
     ... }
function v2() {
    
     ... }

export {
    
    
  v1 as streamV1,
  v2 as streamV2,
  v2 as streamLatestVersion
};

Lo que necesita especial atención es que exportel comando especifica la interfaz externa, que debe establecer una correspondencia uno a uno con las variables dentro del módulo.

// 报错
export 1;

// 报错
var m = 1;
export m;

Las dos formas de escritura anteriores informarán un error, porque no se proporciona una interfaz externa. La primera forma de escritura se emite directamente 1, y la segunda forma de escritura mse emite directamente a través de variables 1. 1Solo un valor, no una interfaz. La forma correcta de escribir es la siguiente.

// 写法一
export var m = 1;

// 写法二
var m = 1;
export {
    
    m};

// 写法三
var n = 1;
export {
    
    n as m};

Los tres métodos de escritura anteriores son correctos y especifican la interfaz externa m. Otros scripts pueden obtener el valor 1 a través de esta interfaz. Su esencia es establecer una correspondencia uno a uno entre el nombre de la interfaz y las variables internas del módulo.

Del mismo modo, la salida de functiony classtambién debe seguir esta forma de escritura.

// 报错
function f() {
    
    }
export f;

// 正确
export function f() {
    
    };

// 正确
function f() {
    
    }
export {
    
    f};

4. comando de importación

Después de usar exportel comando para definir la interfaz externa del módulo, otros archivos JS pueden importcargar este módulo a través del comando.

// main.js
import {
    
     firstName, lastName, year } from './profile.js';

function setName(element) {
    
    
  element.textContent = firstName + ' ' + lastName;
}

Si desea cambiar el nombre de la variable de entrada, importel comando debe usar aspalabras clave para cambiar el nombre de la variable de entrada.

import {
    
     lastName as surname } from './profile.js';

importLas variables ingresadas por el comando son todas de solo lectura, porque su esencia es una interfaz de entrada. En otras palabras, no está permitido reescribir la interfaz en el script que carga el módulo.

import {
    
    a} from './xxx.js'

a = {
    
    }; // Syntax Error : 'a' is read-only;

En el código anterior, el script carga la variable ay, si se reasigna, se informará un error, porque a es una interfaz de solo lectura. Sin embargo, si aes un objeto, ase permiten propiedades anuladas.

import {
    
    a} from './xxx.js'

a.foo = 'hello'; // 合法操作

5. Carga total de módulos

Además de especificar cargar un valor de salida determinado, también puede usar la carga general, es decir, usar un asterisco (*) para especificar un objeto, y todos los valores de salida se cargan en este objeto.

A continuación se muestra un archivo circle.js que exporta dos métodos, área y circunferencia.

// circle.js

export function area(radius) {
    
    
  return Math.PI * radius * radius;
}

export function circumference(radius) {
    
    
  return 2 * Math.PI * radius;
}

Ahora, cargue este módulo.

// main.js

import {
    
     area, circumference } from './circle';

console.log('圆面积:' + area(4));
console.log('圆周长:' + circumference(14));

El método anterior es para especificar los métodos que se cargarán uno por uno, y el método de carga general es el siguiente.

import * as circle from './circle';

console.log('圆面积:' + circle.area(4));
console.log('圆周长:' + circle.circumference(14));

Tenga en cuenta que el objeto donde se carga el módulo como un todo (círculo en el ejemplo anterior) debe ser analizable estáticamente, por lo que no se permiten cambios en el tiempo de ejecución. La siguiente escritura no está permitida.

import * as circle from './circle';

// 下面两行都是不允许的
circle.foo = 'hello';
circle.area = function () {
    
    };

6. exportar comando predeterminado

Al usar importel comando, el usuario necesita saber el nombre de la variable o función a cargar, de lo contrario no se puede cargar. Sin embargo, los usuarios definitivamente quieren comenzar rápidamente y es posible que no estén dispuestos a leer la documentación. Entonces, por conveniencia, el comando se usa para export defaultespecificar la salida predeterminada para el módulo.

// export-default.js
export default function () {
    
    
  console.log('foo');
}

El código anterior es un archivo de módulo export-default.jsy su salida predeterminada es una función.

Cuando otros módulos cargan este módulo, importel comando puede especificar cualquier nombre para la función anónima.

// import-default.js
import customName from './export-default';
customName(); // 'foo'

El comando del código anterior importpuede usar cualquier nombre para apuntar al export-default.jsmétodo de salida. En este momento, no es necesario conocer el nombre de la función de salida del módulo original. Cabe señalar que importlas llaves no se utilizan después del comando en este momento.

export defaultTambién es posible usar comandos antes de funciones no anónimas.

// export-default.js
export default function foo() {
    
    
  console.log('foo');
}

// 或者写成

function foo() {
    
    
  console.log('foo');
}

export default foo;

En el código anterior, fooel nombre de función de la función foono es válido fuera del módulo. Al cargar, se considera como una carga de función anónima.

// 第一组
export default function crc32() {
    
     // 输出
  // ...
}

import crc32 from 'crc32'; // 输入

// 第二组
export function crc32() {
    
     // 输出
  // ...
};

import {
    
    crc32} from 'crc32'; // 输入

Los dos grupos de códigos anteriores están escritos, el primer grupo se usa export default, la declaración correspondiente importno necesita usar llaves; el segundo grupo no se usa export default, la declaración correspondiente importnecesita usar llaves.

El comando exportar predeterminado se usa para especificar la salida predeterminada del módulo. Obviamente, un módulo solo puede tener una salida predeterminada, por lo que el comando exportar predeterminado solo se puede usar una vez. Por lo tanto, no es necesario usar llaves después del comando de importación, ya que solo puede corresponder al comando predeterminado de exportación.

En esencia, export defaultes exportar una defaultvariable o método llamado , y luego el sistema te permite darle cualquier nombre. Por lo tanto, el siguiente escrito es válido.

// modules.js
function add(x, y) {
    
    
  return x * y;
}
export {
    
    add as default};
// 等同于
// export default add;

// app.js
import {
    
     default as foo } from 'modules';
// 等同于
// import foo from 'modules';

7. Escritura compuesta de exportación e importación

Si en un módulo, el mismo módulo se ingresa primero y luego se emite, importla declaración se puede exportescribir junto con la declaración.

export {
    
     foo, bar } from 'my_module';

// 可以简单理解为
import {
    
     foo, bar } from 'my_module';
export {
    
     foo, bar };

En el código anterior, la instrucción exportAND importse puede combinar y escribir en una sola línea. Sin embargo, debe tenerse en cuenta que después de escribirse en una línea, fooy baren realidad no se importa al módulo actual, sino que es equivalente a reenviar estas dos interfaces externamente, de modo que el módulo actual no puede usar directamente fooy bar.

El cambio de nombre de la interfaz y la salida general del módulo también se pueden escribir de esta manera.

// 接口改名
export {
    
     foo as myFoo } from 'my_module';

// 整体输出
export * from 'my_module';

La interfaz predeterminada se escribe de la siguiente manera.

export {
    
     default } from 'foo';

El método de escritura para cambiar la interfaz con nombre a la interfaz predeterminada es el siguiente.

export {
    
     es6 as default } from './someModule';

// 等同于
import {
    
     es6 } from './someModule';
export default es6;

Del mismo modo, la interfaz predeterminada también se puede renombrar a una interfaz con nombre.

export {
    
     default as es6 } from './someModule';

Antes de ES2020, había una declaración de importación, pero no había un método de escritura compuesto correspondiente.

import * as someIdentifier from "someModule";

ES2020 agregó esta forma de escribir.

export * as ns from "mod";

// 等同于
import * as ns from "mod";
export {
    
    ns};

Supongo que te gusta

Origin blog.csdn.net/Bon_nenul/article/details/128315440
Recomendado
Clasificación