목차
Node.js
module.exports
require('id')
模块类型
模块名
文件路径
单次加载 & 循环依赖
Module type
모듈 이름
파일 경로
단일 로드 및 순환 종속성
工作原理
在 Node.js 中使用 ES Module
babel 构建
原生支持
웹 프론트엔드 JS 튜토리얼 Node.js의 모듈 시스템 이해

Node.js의 모듈 시스템 이해

Nov 24, 2020 pm 05:58 PM
node.js 모듈 시스템

Node.js의 모듈 시스템 이해

관련 추천: "node js tutorial"

Node.js

JavaScript의 모듈은 웹 페이지에 대화형 기능을 추가하기 위한 간단한 스크립트 언어로 나왔습니다. 처음에는 모듈 시스템이 포함되어 있지 않았습니다. JavaScript는 점점 더 복잡해지는 문제를 해결합니다. 모든 코드를 하나의 파일에 작성하고 기능 단위를 구별하는 기능을 사용하면 더 이상 복잡한 애플리케이션 개발을 지원할 수 없습니다. ES6은 대부분의 고급 언어에 공통적인 클래스와 모듈을 제공하므로 개발자가 더 쉽게 구성할 수 있습니다.

import _ from 'lodash';

class Fun {}

export default Fun;
로그인 후 복사

위 세 줄의 코드는 모듈 시스템의 가장 중요한 두 가지 요소인 가져오기와 내보내기를 보여줍니다.

  • 내보내기는 모듈의 외부 인터페이스를 지정하는 데 사용됩니다export用于规定模块的对外接口

  • import用于输入其他模块提供的功能

而在 ES6 之前,社区出现了很多模块加载方案,最主要的有 CommonJS 和 AMD 两种,Node.js 诞生早于 ES6,模块系统使用的是类似 CommonJS 的实现,遵从几个原则

  • 一个文件是一个模块,文件内的变量作用域都在模块内

  • 使用 module.exports 对象导出模块对外接口

  • 使用 require 引入其它模块

circle.js

const { PI } = Math;

module.exports = function area(r) {
  PI * r ** 2;
};
로그인 후 복사

上面代码就实现了 Node.js 的一个模块,模块没有依赖其它模块,导出了方法 area 计算圆的面积

test.js

const area = require('./circle.js');
console.log(`半径为 4 的圆的面积是 ${area(4)}`);
로그인 후 복사

模块依赖了 circle.js,使用其对外暴露的 area 方法,计算圆的面积

module.exports

模块对外暴露接口使用 module.exports,常见的有两种用法:为其添加属性或赋值到新对象
test.js

// 添加属性
module.exports.prop1 = xxx;
module.exports.funA = xxx;
module.exports.funB = xxx;

// 赋值到全新对象
module.exports = {
  prop1,
	funA,
  funB,
};
로그인 후 복사

两种写法是等价的,使用时候没区别

const mod = require('./test.js');

console.log(mod.prop1);
console.log(mod.funA());
로그인 후 복사

还有另外一种直接使用 exports 对象的方法,但是只能对其添加属性,不能赋值到新对象,后面会介绍原因

// 正确的写法:添加属性
exports.prop1 = xxx;
exports.funA = xxx;
exports.funB = xxx;

// 赋值到全新对象
module.exports = {
  prop1,
	funA,
  funB,
};
로그인 후 복사

require('id')

模块类型

require 用法比较简单,id 支持模块名和文件路径两种类型

模块名

const fs = require('fs');
const _ = require('lodash');
로그인 후 복사

示例中的 fs、lodash 都是模块名,fs 是 Node.js 内置的核心模块,lodash 是通过 npm 安装到 node_modules 下的第三方模块,如果出现重名,优先使用系统内置模块

因为一个项目内可能会包含多个 node_modules 文件夹(Node.js 比较失败的设计),第三方模块查找过程会遵循就近原则逐层上溯(可以在程序中打印 module.paths 查看具体查找路径),直到根据 NODE_PATH 环境变量查找到文件系统根目录,具体过程可以参考官方文档

此外,Node.js 还会搜索以下的全局目录列表:

  • $HOME/.node_modules
  • $HOME/.node_libraries
  • $PREFIX/lib/node

其中 $HOME 是用户的主目录, $PREFIX 是 Node.js 里配置的 node_prefix。强烈建议将所有的依赖放在本地的 node_modules 目录,这样将会更快地加载,且更可靠

文件路径

模块还可以可以使用文件路径加载,这是项目内自定义模块的通用加载方式,路径可以省略拓展名,会按照 .js、.json、.node 顺序尝试

  • '/' 为前缀的模块是文件的绝对路径,按照系统路径查找模块
  • './' 为前缀的模块是相对于当前调用 require 方法的文件,不受后续模块在哪里被使用到影响

单次加载 & 循环依赖

模块在第一次加载后会被缓存到 Module._cache ,如果每次调用 require('foo') 都解析到同一文件,则返回相同的对象,同时多次调用 require(foo) 不会导致模块的代码被执行多次。 Node.js 根据实际的文件名缓存模块,因此从不同层级目录引用相同模块不会重复加载。

理解的模块单次加载机制方便我们理解模块循环依赖后的现象
a.js

console.log('a 开始');
exports.done = false;
const b = require('./b.js');
console.log('在 a 中,b.done = %j', b.done);
exports.done = true;
console.log('a 结束');
로그인 후 복사

b.js

console.log('b 开始');
exports.done = false;
const a = require('./a.js');
console.log('在 b 中,a.done = %j', a.done);
exports.done = true;
console.log('b 结束');
로그인 후 복사

main.js li>

import는 다른 모듈에서 제공하는 기능을 가져오는 데 사용됩니다

ES6 이전에는 커뮤니티에 많은 모듈 로딩 솔루션이 등장했는데 가장 중요한 솔루션은 CommonJS와 AMD와 Node.js가 탄생했습니다. ES6 이전에는 모듈 시스템이 CommonJS와 유사한 구현을 사용하여 여러 원칙을 따릅니다

파일은 모듈이고 파일의 변수 범위는 모듈 내에 있습니다

🎜🎜module .exports 객체 내보내기 모듈 외부 인터페이스 사용🎜🎜🎜require를 사용하여 다른 모듈 도입🎜 🎜circle.js 🎜
console.log('main 开始');
const a = require('./a.js');
const b = require('./b.js');
console.log('在 main 中,a.done=%j,b.done=%j', a.done, b.done);
로그인 후 복사
🎜위 코드는 Node.js의 모듈을 구현한 것입니다. 이 모듈은 다른 모듈에 의존하지 않으며 area 메소드를 내보내서 면적을 계산합니다. ​​원🎜🎜test.js🎜
main 开始
a 开始
b 开始
在 b 中,a.done = false
b 结束
在 a 中,b.done = true
a 结束
在 main 中,a.done=true,b.done=true
로그인 후 복사
로그인 후 복사
🎜모듈은 Circle.js를 사용하며 외부 노출 면적 방법을 사용하여 원의 면적을 계산합니다🎜

module.exports🎜🎜모듈의 외부에 노출된 인터페이스는 module.exports를 사용합니다. 두 가지 일반적인 사용법이 있습니다: 새 객체에 속성을 추가하거나 값을 할당합니다🎜test.js🎜
(function(exports, require, module, __filename, __dirname) {
	// 模块的代码实际上在这里
});
로그인 후 복사
로그인 후 복사
🎜둘 작성 방법은 동일하며 사용시 차이가 없습니다🎜
const exports = module.exports;
(function(exports, require, module, __filename, __dirname) {
	// 模块的代码实际上在这里
});
로그인 후 복사
로그인 후 복사
🎜exports 개체 방법을 직접 사용하는 방법도 있지만 속성만 추가할 수 있고 새 개체에 할당할 수는 없습니다. 이유는 나중에 소개하겠습니다🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">{   &quot;presets&quot;: [     [&quot;@babel/preset-env&quot;, {       &quot;targets&quot;: {         &quot;node&quot;: &quot;8.9.0&quot;,         &quot;esmodules&quot;: true       }           }]   ] }</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div> <h2 id="requireid">require('id')🎜<h3 id="Module-type">Module type</h3>🎜require 사용법은 비교적 간단하며 id는 두 가지 유형을 지원합니다. 모듈 이름 및 파일 경로🎜<h4 id="모듈-이름">모듈 이름</h4>rrreee🎜fs와 예제의 lodash는 모두 모듈 이름입니다. fs는 Node.js에 내장된 핵심 모듈이고 lodash는 npm을 통해 <code>node_modules 아래에 설치된 타사 모듈. 중복된 이름이 있는 경우 프로젝트에 여러 node_modules 폴더가 포함될 수 있으므로 시스템 내장 모듈을 사용하는 것이 우선입니다(상대적으로 실패한 설계). Node.js), 타사 모듈 검색 프로세스는 근접성 원칙을 따르고 계층별로 올라갑니다(특정 검색 경로를 보려면 프로그램에서 module.paths를 인쇄할 수 있음). NODE_PATH 환경 변수에 따라 파일 시스템 루트 디렉터리를 찾으세요. 특정 프로세스는 공식 문서를 참조하세요🎜🎜또한 Node.js는 다음 전역 디렉터리 목록도 검색합니다.🎜🎜$HOME/.node_modules 🎜$HOME/.node_libraries🎜$PREFIX/lib/node🎜여기서 $HOME는 사용자의 홈 디렉터리인 $ PREFIX는 Node.js에 구성된 node_prefix입니다. 모든 종속성을 로컬 node_modules 디렉터리에 배치하는 것이 좋습니다. 이렇게 하면 더 빠르게 로드되고 더 안정적이 됩니다.🎜

파일 경로

🎜모듈은 파일 경로를 사용하여 로드할 수도 있습니다. 프로젝트의 커스텀 모듈에 대한 일반적인 로딩 방법은 경로 확장을 생략할 수 있으며, '/' 접두사가 붙은 모듈은 .js, .json, .node🎜🎜 파일의 절대 경로이며, 시스템 경로에 따라 모듈을 검색합니다.🎜 './' 접두사가 붙은 모듈은 현재 require 메소드를 호출하는 파일에 상대적이며, 후속 모듈이 사용되는 위치에 영향을 받지 않습니다.

단일 로드 및 순환 종속성

🎜모듈은 첫 번째 로드 ._cache 이후 모듈, require('foo')에 대한 각 호출이 동일한 파일로 확인되면 동일한 객체가 반환되고 require(foo) 는 여러 번 호출됩니다. > 모듈의 코드가 여러 번 실행되지 않습니다. Node.js는 실제 파일 이름을 기반으로 모듈을 캐시하므로 다른 디렉터리 수준에서 참조할 때 동일한 모듈이 두 번 로드되지 않습니다. 🎜🎜잘 알려진 모듈 단일 로딩 메커니즘은 모듈 순환 종속성 현상에 대한 이해를 돕습니다🎜a.js🎜rrreee🎜b.js🎜rrreee🎜 main.js:🎜rrreee🎜main.js가 a.js를 로드하면 a.js는 b.js를 로드합니다. 이때 b.js는 무한 루프를 방지하기 위해 a.js를 로드하려고 합니다. , a.js의 내보내기 개체의 🎜미완성 복사본🎜이 b.js 모듈에 제공된 다음 b.js가 로드를 완료하고 내보내기 개체를 a.js 모듈🎜🎜에 제공하므로 다음의 출력이 반환됩니다. 예는 🎜
main 开始
a 开始
b 开始
在 b 中,a.done = false
b 结束
在 a 中,b.done = true
a 结束
在 main 中,a.done=true,b.done=true
로그인 후 복사
로그인 후 복사

看不懂上面的过程也没关系,日常工作根本用不到,即使看懂了也不要在项目中使用循环依赖!

工作原理

Node.js 每个文件都是一个模块,模块内的变量都是局部变量,不会污染全局变量,在执行模块代码之前,Node.js 会使用一个如下的函数封装器将模块封装

(function(exports, require, module, __filename, __dirname) {
	// 模块的代码实际上在这里
});
로그인 후 복사
로그인 후 복사
  • __filename:当前模块文件的绝对路径
  • __dirname:当前模块文件据所在目录的绝对路径
  • module:当前的模块实例
  • require:加载其它模块的方法,module.require 的快捷方式
  • exports:导出模块接口的对象,module.exports 的快捷方式

回头看看最开始的问题,为什么 exports 对象不支持赋值为其它对象?把上面函数添加一句 exports 对象来源就很简单了

const exports = module.exports;
(function(exports, require, module, __filename, __dirname) {
	// 模块的代码实际上在这里
});
로그인 후 복사
로그인 후 복사

其它模块 require 到的肯定是模块的 module.exports 对象,如果吧 exports 对象赋值给其它对象,就和 module.exports 对象断开了连接,自然就没用了

在 Node.js 中使用 ES Module

随着 ES6 使用越来越广泛,Node.js 也支持了 ES6 Module,有几种方法

babel 构建

使用 babel 构建是在 v12 之前版本最简单、通用的方式,具体配置参考 @babel/preset-env(https://babeljs.io/docs/en/babel-preset-env)

.babelrc

{
  "presets": [
    ["@babel/preset-env", {
      "targets": {
        "node": "8.9.0",
        "esmodules": true
      }      
    }]
  ]
}
로그인 후 복사
로그인 후 복사

原生支持

在 v12 后可以使用原生方式支持 ES Module

  • 开启 --experimental-modules

  • 模块名修改为 .mjs (强烈不推荐使用)或者 package.json 中设置 "type": module

这样 Node.js 会把 js 文件都当做 ES Module 来处理,更多详情参考官方文档(https://nodejs.org/dist/latest-v13.x/docs/api/esm.html)

更多编程相关知识,请访问:编程视频!!

위 내용은 Node.js의 모듈 시스템 이해의 상세 내용입니다. 자세한 내용은 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 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

<gum> : Bubble Gum Simulator Infinity- 로얄 키를 얻고 사용하는 방법
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
Nordhold : Fusion System, 설명
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora : 마녀 트리의 속삭임 - Grappling Hook 잠금 해제 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

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

SublimeText3 중국어 버전

SublimeText3 중국어 버전

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

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

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

Node V8 엔진의 메모리와 GC에 대한 자세한 그래픽 설명 Node V8 엔진의 메모리와 GC에 대한 자세한 그래픽 설명 Mar 29, 2023 pm 06:02 PM

이 기사는 NodeJS V8 엔진의 메모리 및 가비지 수집기(GC)에 대한 심층적인 이해를 제공할 것입니다. 도움이 되기를 바랍니다.

Node의 메모리 제어에 관한 기사 Node의 메모리 제어에 관한 기사 Apr 26, 2023 pm 05:37 PM

Non-Blocking, Event-Driven 기반으로 구축된 Node 서비스는 메모리 소모가 적다는 장점이 있으며, 대규모 네트워크 요청을 처리하는데 매우 적합합니다. 대규모 요청을 전제로 '메모리 제어'와 관련된 문제를 고려해야 합니다. 1. V8의 가비지 수집 메커니즘과 메모리 제한 Js는 가비지 수집 기계에 의해 제어됩니다.

최고의 Node.js Docker 이미지를 선택하는 방법에 대해 이야기해 볼까요? 최고의 Node.js Docker 이미지를 선택하는 방법에 대해 이야기해 볼까요? Dec 13, 2022 pm 08:00 PM

Node용 Docker 이미지를 선택하는 것은 사소한 문제처럼 보일 수 있지만 이미지의 크기와 잠재적인 취약점은 CI/CD 프로세스와 보안에 상당한 영향을 미칠 수 있습니다. 그렇다면 최고의 Node.js Docker 이미지를 어떻게 선택합니까?

Node.js 19가 공식적으로 출시되었습니다. Node.js의 6가지 주요 기능에 대해 이야기해 보겠습니다! Node.js 19가 공식적으로 출시되었습니다. Node.js의 6가지 주요 기능에 대해 이야기해 보겠습니다! Nov 16, 2022 pm 08:34 PM

Node 19가 정식 출시되었습니다. 이 글에서는 Node.js 19의 6가지 주요 기능에 대해 자세히 설명하겠습니다. 도움이 되셨으면 좋겠습니다!

pkg를 사용하여 Node.js 프로젝트를 실행 파일로 패키징하는 방법에 대해 이야기해 보겠습니다. pkg를 사용하여 Node.js 프로젝트를 실행 파일로 패키징하는 방법에 대해 이야기해 보겠습니다. Dec 02, 2022 pm 09:06 PM

nodejs 실행 파일을 pkg로 패키징하는 방법은 무엇입니까? 다음 기사에서는 pkg를 사용하여 Node 프로젝트를 실행 파일로 패키징하는 방법을 소개합니다. 도움이 되기를 바랍니다.

Node의 파일 모듈에 대해 자세히 이야기해 보겠습니다. Node의 파일 모듈에 대해 자세히 이야기해 보겠습니다. Apr 24, 2023 pm 05:49 PM

파일 모듈은 파일 읽기/쓰기/열기/닫기/삭제 추가 등과 같은 기본 파일 작업을 캡슐화한 것입니다. 파일 모듈의 가장 큰 특징은 모든 메소드가 **동기** 및 ** 두 가지 버전을 제공한다는 것입니다. 비동기**, sync 접미사가 있는 메서드는 모두 동기화 메서드이고, 없는 메서드는 모두 이기종 메서드입니다.

Node의 이벤트 루프에 대해 이야기해 봅시다. Node의 이벤트 루프에 대해 이야기해 봅시다. Apr 11, 2023 pm 07:08 PM

이벤트 루프는 Node.js의 기본 부분이며 메인 스레드가 차단되지 않도록 하여 비동기 프로그래밍을 가능하게 합니다. 이벤트 루프를 이해하는 것은 효율적인 애플리케이션을 구축하는 데 중요합니다. 다음 기사는 Node.js의 이벤트 루프에 대한 심층적인 이해를 제공할 것입니다. 도움이 되기를 바랍니다!

노드가 npm 명령을 사용할 수 없으면 어떻게 해야 합니까? 노드가 npm 명령을 사용할 수 없으면 어떻게 해야 합니까? Feb 08, 2023 am 10:09 AM

노드가 npm 명령을 사용할 수 없는 이유는 환경 변수가 올바르게 구성되지 않았기 때문입니다. 해결 방법은 다음과 같습니다. 1. "시스템 속성"을 엽니다. 2. "환경 변수" -> "시스템 변수"를 찾은 다음 환경을 편집합니다. 3. nodejs 폴더의 위치를 ​​찾습니다. 4. "확인"을 클릭합니다.

See all articles