웹 프론트엔드 JS 튜토리얼 JavaScript 코드 모듈의 상세한 해석 및 분석

JavaScript 코드 모듈의 상세한 해석 및 분석

Jun 20, 2018 pm 02:05 PM
javascript 기준 치수

이 글은 주로 JavaScript 모듈의 사용법과 구문 기본 사항을 소개합니다. 도움이 필요한 친구들이 참고할 수 있습니다.

이 글은 자바스크립트 모듈의 기본 설명이며, 각 모듈의 코드 사용법을 분석하고 설명합니다. 전체 내용은 다음과 같습니다.

자바스크립트 모듈 소개

모듈은 일반적으로 자바스크립트 모듈에서 제공하는 코드를 참조합니다. 프로그래밍 언어 프로그램을 독립적이고 공통적인 코드 단위로 나눌 수 있는 조직적 메커니즘입니다. 소위 모듈화는 주로 코드 분할, 범위 격리, 모듈 간 종속성 관리, 프로덕션 환경에 게시할 때 자동화된 패키징 및 처리와 같은 여러 측면을 해결합니다.

모듈 유지 관리의 장점. 모듈은 독립적이기 때문에 잘 설계된 모듈은 외부 코드의 자체 의존성을 줄여 독립적으로 업데이트하고 개선할 수 있습니다. 네임스페이스. JavaScript에서는 변수가 최상위 함수 외부에서 선언되면 전역적으로 사용할 수 있게 됩니다. 따라서 이름 충돌이 실수로 발생하는 경우가 많습니다. 모듈식 개발을 사용하여 변수를 캡슐화하면 전역 환경을 오염시키는 것을 피할 수 있습니다. 코드를 재사용하세요. 때때로 이전에 작성된 프로젝트의 코드를 새 프로젝트에 복사하는 것을 좋아하지만 이는 문제가 되지 않습니다. 그러나 더 좋은 방법은 모듈 참조를 통해 코드 베이스가 중복되는 것을 피하는 것입니다. CommonJS

CommonJS는 원래 2009년에 Mozilla 엔지니어가 시작한 프로젝트였습니다. 그 목적은 브라우저 외부(예: 서버 측 또는 데스크톱)에서 JavaScript를 모듈 방식으로 개발하고 협업할 수 있도록 하는 것입니다.

CommonJS 사양에서 각 JavaScript 파일은 독립적인 모듈 컨텍스트이며 이 컨텍스트에서 생성된 속성은 기본적으로 비공개입니다. 즉, 파일에 정의된 변수(함수 및 클래스 포함)는 비공개이며 다른 파일에 표시되지 않습니다.

CommonJS 사양의 주요 적용 시나리오는 서버 측 프로그래밍이므로 모듈의 동기 로딩 전략이 채택된다는 점에 유의해야 합니다. 3개의 모듈에 의존하는 경우 코드는 모듈을 하나씩 로드합니다.

이 모듈 구현에는 주로 require와 module이라는 두 가지 키워드가 포함되어 있습니다. 이를 통해 모듈은 일부 인터페이스를 외부 세계에 노출하고 다른 모듈에서 가져와 사용할 수 있습니다.

//sayModule.js
function SayModule () {
 this.hello = function () {
 console.log('hello');
 };

 this.goodbye = function () {
 console.log('goodbye');
 };
}
module.exports = SayModule;
//main.js 引入sayModule.js
var Say = require('./sayModule.js');
var sayer = new Say();
sayer.hello(); //hello
로그인 후 복사

서버측 솔루션인 CommonJS에는 전제 조건으로 호환되는 스크립트 로더가 필요합니다. 스크립트 로더는 모듈을 서로 가져오고 내보내는 require 및 module.exports라는 함수를 지원해야 합니다.

Node.js

Node는 CommonJS에서 몇 가지 아이디어를 가져와 자체 모듈식 구현을 만듭니다. 서버 측에서 Node의 인기로 인해 Node의 모듈 형태는 (잘못) CommonJS라고 불립니다.

Node.js 모듈은 두 가지 주요 범주로 나눌 수 있습니다. 하나는 핵심 모듈이고 다른 하나는 파일 모듈입니다.
핵심 모듈은 fs, http, net 등과 같은 Node.js 표준 API에서 제공되는 모듈입니다. Node.js에서 공식적으로 제공하는 모듈이며, 핵심 모듈은 require를 통해 직접 얻을 수 있습니다. 예를 들어 require('fs')의 경우 핵심 모듈의 로딩 우선순위가 가장 높습니다. 핵심 모듈과 모듈 이름 지정 충돌이 있는 경우 Node.js는 항상 핵심 모듈을 로드합니다.
파일 모듈은 JavaScript 코드, JSON 또는 컴파일된 C/C++ 코드일 수 있는 별도의 파일(또는 폴더)로 저장된 모듈입니다. 파일 모듈 확장자가 명시적으로 지정되지 않은 경우 Node.js는 각각 .js, .json 및 .node(컴파일된 C/C++ 코드)를 추가하려고 시도합니다.

로드 방법

경로별로 모듈 로드

요구 매개변수가 "/"로 시작하는 경우 매개변수가 "./", "인 경우 절대 경로에서 모듈 이름을 찾습니다. ./ "이면 상대 경로를 사용하여 모듈을 검색합니다.

node_modules 디렉토리를 검색하여 모듈을 로드하세요

require 매개변수가 "/", "./", "../"로 시작하지 않고 모듈이 핵심 모듈이 아닌 경우 모듈을 로드해야 합니다. node_modules를 검색하여 우리가 npm을 사용하여 얻는 패키지는 일반적으로 이런 방식으로 로드됩니다.

캐시 로드

Node.js 모듈은 로드된 모든 파일 모듈을 파일 이름을 통해 캐시하므로 나중에 액세스할 때 다시 로드되지 않기 때문입니다.
참고: Node.js는 require()에서 제공하는 매개변수가 아닌 실제 파일 이름을 기반으로 캐시됩니다. 즉, require('express') 및 require('./node_modules/express'를 각각 전달하더라도) ) )는 두 번 로드되지만 두 번 로드되지는 않습니다. 왜냐하면 매개변수가 두 번 달라도 구문 분석된 파일은 동일하기 때문입니다.

Node.js의 모듈은 로드 후 싱글톤으로 실행되며 값 전송 원칙을 따릅니다. 객체인 경우 이 객체에 대한 참조와 동일합니다.

모듈 로딩 프로세스

파일 모듈 로딩 작업은 주로 네이티브 모듈 모듈에 의해 구현되고 완료됩니다. 네이티브 모듈은 시작 시 로드되며 프로세스는 runMain 정적 메서드를 직접 호출합니다.

例如运行: node app.js

Module.runMain = function () {
 // Load the main module--the command line argument.
 Module._load(process.argv[1], null, true);
};

//_load静态方法在分析文件名之后执行
var module = new Module(id, parent);

//并根据文件路径缓存当前模块对象,该模块实例对象则根据文件名加载。
module.load(filename);
로그인 후 복사

具体说一下上文提到了文件模块的三类模块,这三类文件模块以后缀来区分,Node.js会根据后缀名来决定加载方法,具体的加载方法在下文require.extensions中会介绍。

.js 通过fs模块同步读取js文件并编译执行。 .node 通过C/C++进行编写的Addon。通过dlopen方法进行加载。 .json 读取文件,调用JSON.parse解析加载。

接下来详细描述js后缀的编译过程。Node.js在编译js文件的过程中实际完成的步骤有对js文件内容进行头尾包装。以app.js为例,包装之后的app.js将会变成以下形式:

//circle.js
var PI = Math.PI;
exports.area = function (r) {
 return PI * r * r;
};
exports.circumference = function (r) {
 return 2 * PI * r;
};

//app.js
var circle = require('./circle.js');
console.log( 'The area of a circle of radius 4 is ' + circle.area(4));
//app包装后
(function (exports, require, module, __filename, __dirname) {
 var circle = require('./circle.js');
 console.log('The area of a circle of radius 4 is ' + circle.area(4));
});
//这段代码会通过vm原生模块的runInThisContext方法执行(类似eval,只是具有明确上下文,不污染全局),返回为一个具体的function对象。最后传入module对象的exports,require方法,module,文件名,目录名作为实参并执行。
로그인 후 복사

这就是为什么require并没有定义在app.js 文件中,但是这个方法却存在的原因。从Node.js的API文档中可以看到还有__filename__dirnamemoduleexports几个没有定义但是却存在的变量。其中__filename__dirname在查找文件路径的过程中分析得到后传入的。module变量是这个模块对象自身,exports是在module的构造函数中初始化的一个空对象({},而不是null)。

在这个主文件中,可以通过require方法去引入其余的模块。而其实这个require方法实际调用的就是load方法。
load方法在载入、编译、缓存了module后,返回module的exports对象。这就是circle.js文件中只有定义在exports对象上的方法才能被外部调用的原因。

以上所描述的模块载入机制均定义在lib/module.js中。

require 函数

require 引入的对象主要是函数。当 Node 调用 require() 函数,并且传递一个文件路径给它的时候,Node 会经历如下几个步骤:

Resolving:找到文件的绝对路径; Loading:判断文件内容类型; Wrapping:打包,给这个文件赋予一个私有作用范围。这是使 require 和 module 模块在本地引用的一种方法; Evaluating:VM 对加载的代码进行处理的地方; Caching:当再次需要用这个文件的时候,不需要重复一遍上面步骤。

require.extensions 来查看对三种文件的支持情况

可以清晰地看到 Node 对每种扩展名所使用的函数及其操作:对 .js 文件使用 module._compile;对 .json 文件使用 JSON.parse;对 .node 文件使用 process.dlopen。

文件查找策略

从文件模块缓存中加载

尽管原生模块与文件模块的优先级不同,但是优先级最高的是从文件模块的缓存中加载已经存在的模块。

从原生模块加载

原生模块的优先级仅次于文件模块缓存的优先级。require方法在解析文件名之后,优先检查模块是否在原生模块列表中。以http模块为例,尽管在目录下存在一个httphttp.jshttp.nodehttp.json文件,require(“http”)都不会从这些文件中加载,而是从原生模块中加载。

原生模块也有一个缓存区,同样也是优先从缓存区加载。如果缓存区没有被加载过,则调用原生模块的加载方式进行加载和执行。

从文件加载

当文件模块缓存中不存在,而且不是原生模块的时候,Node.js会解析require方法传入的参数,并从文件系统中加载实际的文件,加载过程中的包装和编译细节在前面说过是调用module._load方法。
··

当 Node 遇到 require(X) 时,按下面的顺序处理。

(1)如果 X 是内置模块(比如 require('http'))

a. 返回该模块。
b. 不再继续执行。

(2)如果 X 以 "./" 或者 "/" 或者 "../" 开头

a. 根据 X 所在的父模块,确定 X 的绝对路径。
b. 将 X 当成文件,依次查找下面文件,只要其中有一个存在,就返回该文件,不再继续执行。
X
X.js
X.json
X.node

c. 将 X 当成目录,依次查找下面文件,只要其中有一个存在,就返回该文件,不再继续执行。

X/package.json(main字段)
X/index.js
X/index.json
X/index.node

(3)如果 X 不带路径
a. 根据 X 所在的父模块,确定 X 可能的安装目录。
b. 依次在每个目录中,将 X 当成文件名或目录名加载。

(4) 抛出 "not found"

模块循环依赖

//创建两个文件,module1.js 和 module2.js,并且让它们相互引用
 // module1.js
 exports.a = 1;
 require('./module2');
 exports.b = 2;
 exports.c = 3; 
 // module2.js
 const Module1 = require('./module1');
 console.log('Module1 is partially loaded here', Module1);
로그인 후 복사

在 module1 完全加载之前需要先加载 module2,而 module2 的加载又需要 module1。这种状态下,我们从 exports 对象中能得到的就是在发生循环依赖之前的这部分。上面代码中,只有 a 属性被引入,因为 b 和 c 都需要在引入 module2 之后才能加载进来。

Node 使这个问题简单化,在一个模块加载期间开始创建 exports 对象。如果它需要引入其他模块,并且有循环依赖,那么只能部分引入,也就是只能引入发生循环依赖之前所定义的这部分。

AMD

AMD 是 Asynchronous Module Definition 的简称,即“异步模块定义”,是从 CommonJS 讨论中诞生的。AMD 优先照顾浏览器的模块加载场景,使用了异步加载和回调的方式。

AMD 和 CommonJS 一样需要脚本加载器,尽管 AMD 只需要对 define 方法的支持。define 方法需要三个参数:模块名称,模块运行的依赖数组,所有依赖都可用之后执行的函数(该函数按照依赖声明的顺序,接收依赖作为参数)。只有函数参数是必须的。define 既是一种引用模块的方式,也是定义模块的方式。

// file lib/sayModule.js
define(function (){
 return {
 sayHello: function () {
  console.log('hello');
 }
 };
});

//file main.js
define(['./lib/sayModule'], function (say){
 say.sayHello(); //hello
})
로그인 후 복사

main.js 作为整个应用的入口模块,我们使用 define 关键字声明了该模块以及外部依赖(没有生命模块名称);当我们执行该模块代码时,也就是执行 define 函数的第二个参数中定义的函数功能,其会在框架将所有的其他依赖模块加载完毕后被执行。这种延迟代码执行的技术也就保证了依赖的并发加载。

RequireJS

RequireJS 是一个前端的模块化管理的工具库,遵循AMD规范,通过一个函数来将所有所需要的或者说所依赖的模块实现装载进来,然后返回一个新的函数(模块),我们所有的关于新模块的业务代码都在这个函数内部操作,其内部也可无限制的使用已经加载进来的以来的模块。

<script data-main=&#39;scripts/main&#39; src=&#39;scripts/require.js&#39;></script>
//scripts下的main.js则是指定的主代码脚本文件,所有的依赖模块代码文件都将从该文件开始异步加载进入执行。
로그인 후 복사

defined用于定义模块,RequireJS要求每个模块均放在独立的文件之中。按照是否有依赖其他模块的情况分为独立模块和非独立模块。
1、独立模块 不依赖其他模块。直接定义

define({
 methodOne: function (){},
 methodTwo: function (){}
});

//等价于

define(function (){
 return {
 methodOne: function (){},
 methodTwo: function (){}
 };
});
로그인 후 복사

2、非独立模块,对其他模块有依赖

define([ &#39;moduleOne&#39;, &#39;moduleTwo&#39; ], function(mOne, mTwo){
 ...
});

//或者

define( function( require ){
 var mOne = require( &#39;moduleOne&#39; ),
 mTwo = require( &#39;moduleTwo&#39; );
 ...
});
로그인 후 복사

如上代码, define中有依赖模块数组的 和 没有依赖模块数组用require加载 这两种定义模块,调用模块的方法合称为AMD模式,定义模块清晰,不会污染全局变量,清楚的显示依赖关系。AMD模式可以用于浏览器环境并且允许非同步加载模块,也可以按需动态加载模块。

CMD

CMD(Common Module Definition),在CMD中,一个模块就是一个文件。

全局函数define,用来定义模块。
参数 factory 可以是一个函数,也可以为对象或者字符串。
当 factory 为对象、字符串时,表示模块的接口就是该对象、字符串。

定义JSON数据模块:

define({ "foo": "bar" });
로그인 후 복사

factory 为函数的时候,表示模块的构造方法,执行构造方法便可以得到模块向外提供的接口。

define( function(require, exports, module) { 
 // 模块代码
});
로그인 후 복사

SeaJS

sea.js 核心特征:

遵循CMD规范,与NodeJS般的书写模块代码。依赖自动加载,配置清晰简洁。

seajs.use用来在页面中加载一个或者多个模块

 // 加载一个模块 
seajs.use(&#39;./a&#39;);

// 加载模块,加载完成时执行回调
seajs.use(&#39;./a&#39;,function(a){
 a.doSomething();
});

// 加载多个模块执行回调
seajs.use([&#39;./a&#39;,&#39;./b&#39;],function(a , b){
 a.doSomething();
 b.doSomething();
});
로그인 후 복사

AMD和CMD最大的区别是对依赖模块的执行时机处理不同,注意不是加载的时机或者方式不同。

很多人说requireJS是异步加载模块,SeaJS是同步加载模块,这么理解实际上是不准确的,其实加载模块都是异步的,只不过AMD依赖前置,js可以方便知道依赖模块是谁,立即加载,而CMD就近依赖,需要使用把模块变为字符串解析一遍才知道依赖了那些模块,这也是很多人诟病CMD的一点,牺牲性能来带来开发的便利性,实际上解析模块用的时间短到可以忽略。

为什么说是执行时机处理不同?

同样都是异步加载模块,AMD在加载模块完成后就会执行该模块,所有模块都加载执行完后会进入回调函数,执行主逻辑,这样的效果就是依赖模块的执行顺序和书写顺序不一定一致,看网络速度,哪个先下载下来,哪个先执行,但是主逻辑一定在所有依赖加载完成后才执行。

CMD加载完某个依赖模块后并不执行,只是下载而已,在所有依赖模块加载完成后进入主逻辑,遇到require语句的时候才执行对应的模块,这样模块的执行顺序和书写顺序是完全一致的。

UMD

统一模块定义(UMD:Universal Module Definition )就是将 AMD 和 CommonJS 合在一起的一种尝试,常见的做法是将CommonJS 语法包裹在兼容 AMD 的代码中。

(function(define) {
 define(function () {
 return {
  sayHello: function () {
  console.log(&#39;hello&#39;);
  }
 };
 });
}(
 typeof module === &#39;object&#39; && module.exports && typeof define !== &#39;function&#39; ?
 function (factory) { module.exports = factory(); } :
 define
));
로그인 후 복사

该模式的核心思想在于所谓的 IIFE(Immediately Invoked Function Expression),该函数会根据环境来判断需要的参数类别

ES6模块(module) 严格模式

ES6 的模块自动采用严格模式,不管有没有在模块头部加上"use strict";。
严格模式主要有以下限制。

变量必须声明后再使用函数的参数不能有同名属性,否则报错不能使用with语句不能对只读属性赋值,否则报错不能使用前缀0表示八进制数,否则报错不能删除不可删除的属性,否则报错不能删除变量delete prop,会报错,只能删除属性delete global[prop] eval不会在它的外层作用域引入变量 eval和arguments不能被重新赋值 arguments不会自动反映函数参数的变化不能使用arguments.callee 不能使用arguments.caller 禁止this指向全局对象不能使用fn.caller和fn.arguments获取函数调用的堆栈增加了保留字(比如protected、static和interface) 模块Module

一个模块,就是一个对其他模块暴露自己的属性或者方法的文件。

导出Export

作为一个模块,它可以选择性地给其他模块暴露(提供)自己的属性和方法,供其他模块使用。

// profile.js
export var firstName = &#39;qiqi&#39;;
export var lastName = &#39;haobenben&#39;;
export var year = 1992;

//等价于

var firstName = &#39;qiqi&#39;;
var lastName = &#39;haobenben&#39;;
var year = 1992;
export {firstName, lastName, year}
로그인 후 복사

1、 通常情况下,export输出的变量就是本来的名字,但是可以使用as关键字重命名。

function v1() { ... }
function v2() { ... }
export {
 v1 as streamV1,
 v2 as streamV2,
 v2 as streamLatestVersion
};
//上面代码使用as关键字,重命名了函数v1和v2的对外接口。重命名后,v2可以用不同的名字输出两次。
로그인 후 복사

2、 需要特别注意的是,export命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系。

// 报错
export 1;

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

//上面两种写法都会报错,因为没有提供对外的接口。第一种写法直接输出1,第二种写法通过变量m,还是直接输出1。1只是一个值,不是接口。

/ 写法一
export var m = 1;

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

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

//上面三种写法都是正确的,规定了对外的接口m。其他脚本可以通过这个接口,取到值1。它们的实质是,在接口名与模块内部变量之间,建立了一一对应的关系。
로그인 후 복사

3、最后,export命令可以出现在模块的任何位置,只要处于模块顶层就可以。如果处于块级作用域内,就会报错,接下来说的import命令也是如此。

function foo() {
 export default &#39;bar&#39; // SyntaxError
}
foo()
로그인 후 복사

导入import

作为一个模块,可以根据需要,引入其他模块的提供的属性或者方法,供自己模块使用。

1、 import命令接受一对大括号,里面指定要从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块(profile.js)对外接口的名称相同。如果想为输入的变量重新取一个名字,import命令要使用as关键字,将输入的变量重命名。

import { lastName as surename } from &#39;./profile&#39;;
로그인 후 복사

3、注意,import命令具有提升效果,会提升到整个模块的头部,首先执行。

2、import后面的from指定模块文件的位置,可以是相对路径,也可以是绝对路径,.js路径可以省略。如果只是模块名,不带有路径,那么必须有配置文件,告诉 JavaScript 引擎该模块的位置。

foo();

import { foo } from &#39;my_module&#39;;

//上面的代码不会报错,因为import的执行早于foo的调用。这种行为的本质是,import命令是编译阶段执行的,在代码运行之前。
로그인 후 복사

4、由于import是静态执行,所以不能使用表达式和变量,这些只有在运行时才能得到结果的语法结构。

/ 报错
import { &#39;f&#39; + &#39;oo&#39; } from &#39;my_module&#39;;

// 报错
let module = &#39;my_module&#39;;
import { foo } from module;

// 报错
if (x === 1) {
 import { foo } from &#39;module1&#39;;
} else {
 import { foo } from &#39;module2&#39;;
}
로그인 후 복사

5、最后,import语句会执行所加载的模块,因此可以有下面的写法。

import &#39;lodash&#39;;
//上面代码仅仅执行lodash模块,但是不输入任何值。
로그인 후 복사

默认导出(export default)

每个模块支持我们导出一个没有名字的变量,使用关键语句export default来实现.

export default function(){
   console.log("I am default Fn");
  }
//使用export default关键字对外导出一个匿名函数,导入这个模块的时候,可以为这个匿名函数取任意的名字

//取任意名字均可
import sayDefault from "./module-B.js";
sayDefault();
//结果:I am default Fn
로그인 후 복사

1、默认输出和正常输出的比较

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

import diff from &#39;diff&#39;; // 输入

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

import {diff} from &#39;diff&#39;; // 输入

//上面代码的两组写法,第一组是使用export default时,对应的import语句不需要使用大括号;第二组是不使用export default时,对应的import语句需要使用大括号。
로그인 후 복사

export default命令用于指定模块的默认输出。显然,一个模块只能有一个默认输出,因此export default命令只能使用一次。所以,import命令后面才不用加大括号,因为只可能对应一个方法。

2、因为export default本质是将该命令后面的值,赋给default变量以后再默认,所以直接将一个值写在export default之后。

/ 正确
export default 42;

// 报错
export 42;

//上面代码中,后一句报错是因为没有指定对外的接口,而前一句指定外对接口为default。
로그인 후 복사

3、如果想在一条import语句中,同时输入默认方法和其他变量,可以写成下面这样。

import _, { each } from &#39;lodash&#39;;

//对应上面代码的export语句如下
export default function (){
 //...
}
export function each (obj, iterator, context){
 //...
}
로그인 후 복사

export 与 import 的复合写法

如果在一个模块之中,先输入后输出同一个模块,import语句可以与export语句写在一起。

export { foo, bar } from &#39;my_module&#39;;

// 等同于
import { foo, bar } from &#39;my_module&#39;;
export { foo, bar };

/ 接口改名
export { foo as myFoo } from &#39;my_module&#39;;

// 整体输出
export * from &#39;my_module&#39;;
로그인 후 복사

注意事项

1、声明的变量,对外都是只读的。但是导出的是对象类型的值,就可修改。

2、导入不存在的变量,值为undefined。

ES6 中的循环引用

ES6 中,imports 是 exprts 的只读视图,直白一点就是,imports 都指向 exports 原本的数据,比如:

//------ lib.js ------
export let counter = 3;
export function incCounter() {
 counter++;
}

//------ main.js ------
import { counter, incCounter } from &#39;./lib&#39;;

// The imported value `counter` is live
console.log(counter); // 3
incCounter();
console.log(counter); // 4

// The imported value can&#39;t be changed
counter++; // TypeError
로그인 후 복사

因此在 ES6 中处理循环引用特别简单,看下面这段代码:

//------ a.js ------
import {bar} from &#39;b&#39;; // (1)
export function foo() {
 bar(); // (2)
}

//------ b.js ------
import {foo} from &#39;a&#39;; // (3)
export function bar() {
 if (Math.random()) {
 foo(); // (4)
 }
}
로그인 후 복사

假设先加载模块 a,在模块 a 加载完成之后,bar 间接性地指向的是模块 b 中的 bar。无论是加载完成的 imports 还是未完成的 imports,imports 和 exports 之间都有一个间接的联系,所以总是可以正常工作。

实例

//---module-B.js文件---
//导出变量:name
export var name = "cfangxu";

moduleA模块代码:
//导入 模块B的属性 name 
import { name } from "./module-B.js"; 
console.log(name)
//打印结果:cfangxu
로그인 후 복사

批量导出

//属性name
var name = "cfangxu";
//属性age
var age = 26;
//方法 say
var say = function(){
   console.log("say hello");
  }
//批量导出
export {name,age,say}
로그인 후 복사

批量导入

//导入 模块B的属性
import { name,age,say } from "./module-B.js";
console.log(name)
//打印结果:cfangxu
console.log(age)
//打印结果:26
say()
//打印结果:say hello
로그인 후 복사

重命名导入变量

import {name as myName} from &#39;./module-B.js&#39;;
console.log(myName) //cfangxu
로그인 후 복사

整体导入

/使用*实现整体导入
import * as obj from "./module-B.js";

console.log(obj.name)
//结果:"cfangxu"
console.log(obj.age)
//结果:26
obj.say();
//结果:say hello
로그인 후 복사

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

JS를 사용하여 여러 스크롤 막대를 동기식으로 스크롤하는 방법

Webpack 프레임워크(마스터 핵심 기술)

webpack+express를 사용하여 다중 페이지 사이트 개발을 달성하는 방법

JavaScript 모듈 최적화

webpack이 타사 라이브러리를 추출하는 방법 사용

위 내용은 JavaScript 코드 모듈의 상세한 해석 및 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

WLAN 확장 모듈이 중지되었습니다. [수정] WLAN 확장 모듈이 중지되었습니다. [수정] Feb 19, 2024 pm 02:18 PM

Windows 컴퓨터의 WLAN 확장 모듈에 문제가 있는 경우 인터넷 연결이 끊어질 수 있습니다. 이러한 상황은 종종 좌절감을 주지만 다행히도 이 문서에서는 이 문제를 해결하고 무선 연결이 다시 제대로 작동하도록 하는 데 도움이 될 수 있는 몇 가지 간단한 제안 사항을 제공합니다. WLAN 확장성 모듈 복구가 중지되었습니다. Windows 컴퓨터에서 WLAN 확장성 모듈의 작동이 중지된 경우 다음 제안에 따라 문제를 해결하십시오. 네트워크 및 인터넷 문제 해결사를 실행하여 무선 네트워크 연결을 비활성화했다가 다시 활성화하십시오. WLAN 자동 구성 서비스 다시 시작 전원 옵션 수정 수정 고급 전원 설정 네트워크 어댑터 드라이버 재설치 일부 네트워크 명령 실행 이제 자세히 살펴보겠습니다.

WLAN 확장성 모듈을 시작할 수 없습니다. WLAN 확장성 모듈을 시작할 수 없습니다. Feb 19, 2024 pm 05:09 PM

이 문서에서는 무선 LAN 확장 모듈을 시작할 수 없음을 나타내는 이벤트 ID10000을 해결하는 방법을 자세히 설명합니다. 이 오류는 Windows 11/10 PC의 이벤트 로그에 나타날 수 있습니다. WLAN 확장성 모듈은 IHV(독립 하드웨어 공급업체) 및 ISV(독립 소프트웨어 공급업체)가 사용자에게 맞춤형 무선 네트워크 기능을 제공할 수 있도록 하는 Windows의 구성 요소입니다. Windows 기본 기능을 추가하여 기본 Windows 네트워크 구성 요소의 기능을 확장합니다. WLAN 확장성 모듈은 운영 체제가 네트워크 구성 요소를 로드할 때 초기화의 일부로 시작됩니다. 무선 LAN 확장 모듈에 문제가 발생하여 시작할 수 없는 경우 이벤트 뷰어 로그에 오류 메시지가 표시될 수 있습니다.

WebSocket과 JavaScript를 사용하여 온라인 음성 인식 시스템을 구현하는 방법 WebSocket과 JavaScript를 사용하여 온라인 음성 인식 시스템을 구현하는 방법 Dec 17, 2023 pm 02:54 PM

WebSocket 및 JavaScript를 사용하여 온라인 음성 인식 시스템을 구현하는 방법 소개: 지속적인 기술 개발로 음성 인식 기술은 인공 지능 분야의 중요한 부분이 되었습니다. WebSocket과 JavaScript를 기반으로 한 온라인 음성 인식 시스템은 낮은 대기 시간, 실시간, 크로스 플랫폼이라는 특징을 갖고 있으며 널리 사용되는 솔루션이 되었습니다. 이 기사에서는 WebSocket과 JavaScript를 사용하여 온라인 음성 인식 시스템을 구현하는 방법을 소개합니다.

WebSocket 및 JavaScript: 실시간 모니터링 시스템 구현을 위한 핵심 기술 WebSocket 및 JavaScript: 실시간 모니터링 시스템 구현을 위한 핵심 기술 Dec 17, 2023 pm 05:30 PM

WebSocket과 JavaScript: 실시간 모니터링 시스템 구현을 위한 핵심 기술 서론: 인터넷 기술의 급속한 발전과 함께 실시간 모니터링 시스템이 다양한 분야에서 널리 활용되고 있다. 실시간 모니터링을 구현하는 핵심 기술 중 하나는 WebSocket과 JavaScript의 조합입니다. 이 기사에서는 실시간 모니터링 시스템에서 WebSocket 및 JavaScript의 적용을 소개하고 코드 예제를 제공하며 구현 원칙을 자세히 설명합니다. 1. 웹소켓 기술

JavaScript 및 WebSocket을 사용하여 실시간 온라인 주문 시스템을 구현하는 방법 JavaScript 및 WebSocket을 사용하여 실시간 온라인 주문 시스템을 구현하는 방법 Dec 17, 2023 pm 12:09 PM

JavaScript 및 WebSocket을 사용하여 실시간 온라인 주문 시스템을 구현하는 방법 소개: 인터넷의 대중화와 기술의 발전으로 점점 더 많은 레스토랑에서 온라인 주문 서비스를 제공하기 시작했습니다. 실시간 온라인 주문 시스템을 구현하기 위해 JavaScript 및 WebSocket 기술을 사용할 수 있습니다. WebSocket은 TCP 프로토콜을 기반으로 하는 전이중 통신 프로토콜로 클라이언트와 서버 간의 실시간 양방향 통신을 실현할 수 있습니다. 실시간 온라인 주문 시스템에서는 사용자가 요리를 선택하고 주문을 하면

WebSocket과 JavaScript를 사용하여 온라인 예약 시스템을 구현하는 방법 WebSocket과 JavaScript를 사용하여 온라인 예약 시스템을 구현하는 방법 Dec 17, 2023 am 09:39 AM

WebSocket과 JavaScript를 사용하여 온라인 예약 시스템을 구현하는 방법 오늘날의 디지털 시대에는 점점 더 많은 기업과 서비스에서 온라인 예약 기능을 제공해야 합니다. 효율적인 실시간 온라인 예약 시스템을 구현하는 것이 중요합니다. 이 기사에서는 WebSocket과 JavaScript를 사용하여 온라인 예약 시스템을 구현하는 방법을 소개하고 구체적인 코드 예제를 제공합니다. 1. WebSocket이란 무엇입니까? WebSocket은 단일 TCP 연결의 전이중 방식입니다.

Ansible 작동 방식에 대한 자세한 설명 Ansible 작동 방식에 대한 자세한 설명 Feb 18, 2024 pm 05:40 PM

Ansible의 작동 원리는 위 그림에서 이해할 수 있습니다. 관리 측에서는 관리 측에 연결하기 위해 로컬, SSH 및 zeromq의 세 가지 방법을 지원합니다. 기본값은 SSH 기반 연결을 사용하는 것입니다. 위의 아키텍처 다이어그램에서는 HostInventory(호스트 목록) 분류가 다른 방식으로 수행될 수 있습니다. 관리 노드는 단일 모듈 및 단일 명령의 일괄 실행을 구현합니다. -hoc; 관리 노드는 플레이북을 통해 웹 서비스 설치 및 배포, 데이터베이스 서버 일괄 백업 등과 같은 여러 작업 모음을 구현할 수 있습니다. 우리는 플레이북을 시스템이 통과하는 것으로 간단히 이해할 수 있습니다.

JavaScript와 WebSocket: 효율적인 실시간 일기예보 시스템 구축 JavaScript와 WebSocket: 효율적인 실시간 일기예보 시스템 구축 Dec 17, 2023 pm 05:13 PM

JavaScript 및 WebSocket: 효율적인 실시간 일기 예보 시스템 구축 소개: 오늘날 일기 예보의 정확성은 일상 생활과 의사 결정에 매우 중요합니다. 기술이 발전함에 따라 우리는 날씨 데이터를 실시간으로 획득함으로써 보다 정확하고 신뢰할 수 있는 일기예보를 제공할 수 있습니다. 이 기사에서는 JavaScript 및 WebSocket 기술을 사용하여 효율적인 실시간 일기 예보 시스템을 구축하는 방법을 알아봅니다. 이 문서에서는 특정 코드 예제를 통해 구현 프로세스를 보여줍니다. 우리

See all articles