현재 거의 모든 프로젝트는 웹팩, 롤업 및 기타 빌드 도구를 기반으로 개발되었으며 모듈화가 표준이 되었습니다.
오늘은 ES6의 모듈 메커니즘을 체계적으로 검토하고 일반적인 작업과 모범 사례를 요약하겠습니다.
몇 가지 간단한 배경
사용 준비가 완료되었으며 우리 모두가 달성하고자 하는 메커니즘입니다.
Javascript에서도 마찬가지입니다. 큰 Javascript 프로그램을 여러 부분으로 나누어서 사용할 부분만 가져가세요.
[관련 과정 권장 사항: JavaScript 비디오 튜토리얼]
오랫동안 NodeJS에는 이러한 기능이 있었으며 나중에 점점 더 많은 라이브러리와 프레임워크에도 CommonJS 또는 AMD 모델 기반 구현과 같은 모듈 기능이 있습니다. RequireJs와 같은) 및 후속 Webpack, Babel 등
2015년에는 표준 모듈형 시스템이 탄생했습니다. 이것이 오늘 이야기할 주인공인 ES6 모델 시스템입니다.
언뜻 보면 ES6 모델 시스템이 CommonJS 구문과 매우 유사하다는 것을 쉽게 알 수 있습니다. 결국 ES6 모델 시스템은 CommonJS 시대에서 왔으며 CommonJS의 영향을 많이 받았습니다.
CommonJs와 같은 간단한 예를 살펴보세요: (https://flaviocopes.com/commonjs/)
//file.js module.exports = value; // 引入value const value = require('file.js')
그리고 ES6에서는:
// const.js export const value = 'xxx'; import { value } from 'const.js'
구문은 매우 유사합니다.
이제 ES6 모듈에 대해 자세히 알아보기 위해 주로 가져오기 및 내보내기 및 여러 관련 기능을 살펴보겠습니다.
모듈화의 이점
모듈화의 주요 이점은 두 가지입니다.
1. 避免全局变量污染 2. 有效的处理依赖关系
시대가 발전하면서 브라우저도 es6 가져오기 및 내보내기 구문을 기본적으로 지원하기 시작했습니다.
먼저 간단한 예를 살펴보겠습니다.
<script> import { addTextToBody } from '/util.js'; addTextToBody('Modules are pretty cool.'); </script> // util.js export function addTextToBody(text) { const p = document.createElement('p'); p.textContent = text; document.body.appendChild(p); }
이벤트를 처리하려는 경우에도 마찬가지입니다. 간단한 예를 살펴보겠습니다.
<button>Show Message</button> <script></script> // showImport.js import { showMessage } from '/show.js' document.getElementById('test').onclick = function() { showMessage(); } // show.js export function showMessage() { alert("Hello World!") }
이 데모를 실행하려면 다음을 설정해야 합니다. 간단한 서비스 시작:
$ http-server
그렇지 않으면 CORS 오류가 발생합니다.
오류의 구체적인 이유와 기타 세부 사항은 이 글의 초점이 아닙니다. 관심이 있으시면 다음 링크를 자세히 읽어보실 수 있습니다.
https://jakearchibald.com/2017/es-modules-in-browsers/
엄격 모드
https://developer.mozilla.org/en-US/docs/Web/JavaScript/ Reference/Strict_mode
'use strict' 문은 우리에게 익숙합니다. es5 시대에 자주 사용하는 문입니다. 일반적으로 이 문은 Javascript의 친숙하지 않은 부분을 비활성화하고 도움을 주기 위한 것입니다. 더 엄격하게 코드를 작성하세요.
이 기능은 es6 구문에서 기본적으로 활성화됩니다. 코드에 덜 엄격한 코드가 있으면 오류가 보고됩니다. 예:
다음은 MDN에서 추출한 몇 가지 엄격한 코드입니다. <code>비활성화
된 패턴 부분: 严格模式
中被禁用
的部分:
Variables can’t be left undeclared
Function parameters
must have unique names
(or are considered syntax errors)with
is forbiddenread-only properties
Octal numbers
like 00840 are syntax errors
delete undeletable properties
throw an errordelete prop
is a syntax error, instead of assuming delete global[prop]eval
doesn’t introduce new variables into its surrounding scopeeval
and arguments can’t be bound or assigned toarguments
doesn’t magically track changes to method parametersarguments.callee
throws a TypeError, no longer supportedarguments.caller
throws a TypeError, no longer supportedfn.caller
and fn.arguments to access the JavaScript stackReserved words
변수는 선언되지 않은 채로 둘 수 없습니다
함수 매개변수에는 <code>고유한 이름
이 있어야 합니다(또는 구문 오류로 간주됩니다)with
는 금지됩니다
read-에 할당하면 오류가 발생합니다. 00840과 같은 속성
8진수
만 구문 오류
입니다.삭제할 수 없는 속성을 삭제
하려고 하면 오류가 발생합니다. delete prop
은 구문 오류입니다. delete global[prop]eval
이 주변 범위에 새 변수를 도입하지 않는다고 가정하는 대신eval
및 인수는
인수
에 바인딩되거나 할당될 수 없습니다. 메소드 매개변수인수에 대한 변경 사항을 마술처럼 추적하지 않습니다. 피호출자
는 더 이상 지원되지 않는 TypeError를 발생시킵니다.
arguments.caller
는 더 이상 지원되지 않는 TypeError를 발생시킵니다.fn.caller
및 fn.arguments를 사용하여 JavaScript 스택예약어
에 액세스할 수 없습니다(예: protected). , static, 인터페이스 등)은 바인딩할 수 없습니다
여러 가지 내보내기 용도
ES6 모듈은 정적 내보내기만 지원하며 모듈의 가장 바깥쪽 범위에서만 내보내기를 사용할 수 있으며 조건문에서는 사용할 수 없습니다. . , 함수 범위에서도 사용할 수 없습니다.
🎜분류 측면에서 내보내기에는 세 가지 주요 유형이 있습니다. 🎜🎜1. 명명된 내보내기(모듈당 0개 이상의 내보내기) 🎜🎜2. 기본 내보내기(모듈당 1개) 🎜🎜3. 개요: 🎜 🎜// Exporting inpidual features export let name1, name2, …, nameN; // also var, const export let name1 = …, name2 = …, …, nameN; // also var, const export function functionName(){...} export class ClassName {...} // Export list export { name1, name2, …, nameN }; // Renaming exports export { variable1 as name1, variable2 as name2, …, nameN }; // Exporting destructured assignments with renaming export const { name1, name2: bar } = o; // Default exports export default expression; export default function (…) { … } // also class, function* export default function name1(…) { … } // also class, function* export { name1 as default, … }; // Aggregating modules export * from …; // does not set the default export export * as name1 from …; export { name1, name2, …, nameN } from …; export { import1 as name1, import2 as name2, …, nameN } from …; export { default } from …;🎜 이제 내보내기의 일반적인 사용법을 소개하겠습니다. 🎜
1. Named exports (导出每个函数/变量)
具名导出,这种方式导出多个函数,一般使用场景比如 utils、tools、common 之类的工具类函数集,或者全站统一变量等。
只需要在变量或函数前面加 export
关键字即可。
//------ lib.js ------ export const sqrt = Math.sqrt; export function square(x) { return x * x; } export function diag(x, y) { return sqrt(square(x) + square(y)); } //------ main.js 使用方式1 ------ import { square, diag } from 'lib'; console.log(square(11)); // 121 console.log(diag(4, 3)); // 5 //------ main.js 使用方式2 ------ import * as lib from 'lib'; console.log(lib.square(11)); // 121 console.log(lib.diag(4, 3)); // 5
我们也可以直接导出一个列表,例如上面的lib.js可以改写成:
//------ lib.js ------ const sqrt = Math.sqrt; function square(x) { return x * x; } function add (x, y) { return x + y; } export { sqrt, square, add }
2. Default exports (导出一个默认 函数/类)
这种方式比较简单,一般用于一个类文件,或者功能比较单一的函数文件使用。
一个模块中只能有一个export default默认输出。
export default与export的主要区别有两个:
不需要知道导出的具体变量名, 导入(import)时不需要{}.
//------ myFunc.js ------ export default function () {}; //------ main.js ------ import myFunc from 'myFunc'; myFunc();
导出一个类
//------ MyClass.js ------ class MyClass{} export default MyClass; //------ Main.js ------ import MyClass from 'MyClass';
注意这里默认导出不需要用{}。
3. Mixed exports (混合导出)
混合导出,也就是 上面第一点和第二点结合在一起的情况。比较常见的比如 Lodash,都是这种组合方式。
//------ lib.js ------ export var myVar = ...; export let myVar = ...; export const MY_CONST = ...; export function myFunc() { // ... } export function* myGeneratorFunc() { // ... } export default class MyClass { // ... } // ------ main.js ------ import MyClass, { myFunc } from 'lib';
再比如lodash例子:
//------ lodash.js ------ export default function (obj) { // ... }; export function each(obj, iterator, context) { // ... } export { each as forEach }; //------ main.js ------ import _, { forEach } from 'lodash';
4. Re-exporting (别名导出)
一般情况下,export输出的变量就是在原文件中定义的名字,但也可以用 as 关键字来指定别名,这样做一般是为了简化或者语义化export的函数名。
//------ lib.js ------ export function getUserName(){ // ... }; export function setName(){ // ... }; //输出别名,在import的时候可以同时使用原始函数名和别名 export { getName as get, //允许使用不同名字输出两次 getName as getNameV2, setName as set }
5. Module Redirects (中转模块导出)
有时候为了避免上层模块导入太多的模块,我们可能使用底层模块作为中转,直接导出另一个模块的内容如下:
//------ myFunc.js ------ export default function() {...}; //------ lib.js ------ export * from 'myFunc'; export function each() {...}; //------ main.js ------ import myFunc, { each } from 'lib'; export 只支持在最外层静态导出、只支持导出变量、函数、类,如下的几种用法都是错误的。 `错误`的export用法: //直接输出变量的值 export 'Mark'; // 未使用中括号 或 未加default // 当只有一个导出数,需加default,或者使用中括号 var name = 'Mark'; export name; //export不要输出块作用域内的变量 function () { var name = 'Mark'; export { name }; }
import的几种用法
import的用法和export是一一对应的,但是import支持静态导入和动态导入两种方式,动态import支持晚一些,兼容性要差一些。
下面我就总结下import的基本用法:
1. Import All things
当export有多个函数或变量时,如文中export的第一点,可以使用 * as 关键字来导出所有函数及变量,同时 as 后面跟着的名称做为 该模块的命名空间。
//导出lib的所有函数及变量 import * as lib from 'lib'; //以 lib 做为命名空间进行调用,类似于object的方式 console.log(lib.square(11)); // 121
2. Import a single/multiple export from a module
从模块文件中导入单个或多个函数,与 * as namepage 方式不同,这个是按需导入。如下例子:
//导入square和 diag 两个函数 import { square, diag } from 'lib'; // 只导入square 一个函数 import { square } from 'lib'; // 导入默认模块 import _ from 'lodash'; // 导入默认模块和单个函数,这样做主要是简化单个函数的调用 import _, { each } from 'lodash';
3. Rename multiple exports during import
和 export 一样,也可以用 as 关键字来设置别名,当import的两个类的名字一样时,可以使用 as 来重设导入模块的名字,也可以用as 来简化名称。
比如:
// 用 as 来 简化函数名称 import { reallyReallyLongModuleExportName as shortName, anotherLongModuleName as short } from '/modules/my-module.js'; // 避免重名 import { lib as UserLib} from "alib"; import { lib as GlobalLib } from "blib";
4. Import a module for its side effects only
有时候我们只想import一个模块进来,比如样式,或者一个类库。
// 导入样式 import './index.less'; // 导入类库 import 'lodash';
5. Dynamic Imports
静态import在首次加载时候会把全部模块资源都下载下来.
我们实际开发时候,有时候需要动态import(dynamic import)。
例如点击某个选项卡,才去加载某些新的模块:
// 当动态import时,返回的是一个promise import('lodash') .then((lodash) => { // Do something with lodash. }); // 上面这句实际等同于 const lodash = await import('lodash');
es7的新用法:
async function run() { const myModule = await import('./myModule.js'); const { export1, export2 } = await import('./myModule.js'); const [module1, module2, module3] = await Promise.all([ import('./module1.js'), import('./module2.js'), import('./module3.js'), ]); } run();
总结
以上, 我总结了ES6 Module 的简单背景和 常见的import , export 用法, 但这远远不是它的全部, 篇幅有限,如果想了解更多, 可以看下面的延伸阅读部分(质量都还不错, 可以看看)。
本文来自 js教程 栏目,欢迎学习!
위 내용은 ES6 모듈에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!