概述
什么是模块化
- 将程序文件依据一定规则拆分成多个文件,这种编码方式就是模块化的编码方式
- 拆分出来的每个文件就是一个模块,模块中的数据都是私有的,模块之间互相隔离
- 同时也能通过一些手段,把模块内的指定数据“交出去”,供其他模块使用
为什么需要模块化
随着应用的复杂度越来越高,其代码量和文件数量都会急剧增加,会逐渐引发以下问题:
- 全局污染问题
- 依赖混乱问题
- 数据安全问题
有哪些模块化规范?
随着时间的推移,针对 JavaScript 的不同运行环境,相继出现了多种模块化规范,按时间排序,分别为:
- CommonJS 服务端应用广泛
- AMD
- CMD
- ES6 模块化 浏览器端应用广泛
导入与导出
模块化的核心思想是:模块之间是隔离的,通过导入和导出进行数据和功能的共享。
- 导出(暴露):模块公开其内部的一部分(如变量、函数等),使这些内容可以被其他模块使用
- 导入(引入):模块引入和使用其他模块导出的内容,以重用代码和功能
CommonJS 规范
导出数据
在 CommonJS 标准中,导出数据有两种方式:
- 第一种方式:module.exports = value
- 第二种方式:exports.name = value
// a.js
const name = '张三'
function getTel() {
return '123456789'
}
module.exports = { name, getTel }
// b.js
const name = '李四'
function getTel() {
return '666666666'
}
// 通过给exports对象添加属性的方式,来导出数据
exports.name = name
exports.getTel = getTel
// index.js
// 引入a模块暴露的所有内容
const a = require('./a')
// 引入b模块暴露的所有内容
const b = require('./b')
console.log(a, a.getTel())
console.log(b, b.getTel())
注意点:
- 每个模块内部的this、exports、modules.exports在初始时,都指向同一个空对象,该空对象就是当前模块导出的数据
- 无论如何修改导出对象,最终导出的都是module.exports的值
- exports是对module.exports的初始引用,仅为了方便给导出象添加属性,所以不能使用exports = value的形式导出数据,但是可以使用module.exports = value导出数据
导入数据
在CJS模块化标准中,使用内置的require函数进行导入数据。
// index.js
// 1 直接引入模块
const a = require('./a')
console.log(a, a.getTel())
// 2 引入同时解构出要用的数据
const { name, getTel } = require('./a')
console.log(name, getTel())
// 3 引入同时解构 + 重命名
const { name: stuName, getTel: stuTel } = require('./a')
console.log(stuName, stuTel())
扩展理解
一个 JS 模块在执行时,是被包裹在一个内置函数中执行的,所以每个模块都有自己的作用域,可通过如下方式来验证这一说法:
// index.js
console.log(arguments.callee.toString())
内置函数大致形式如下:
function (exports, require, module, __filename, __dirname) {
// index.js
console.log(arguments.callee.toString())
}
浏览器端运行
Node.js 默认支持 CommonJS 规范,但浏览器端不支持,所以需要经过编译,步骤如下:
- 第一步:全局安装 browserify :
pnpm i browserify -g
- 第二步:编译:
browserify index.js -o build.js
,index.js 是源文件,build.js 是输出目标文件 - 第三步:在index.html页面中引入使用:
<script type="text/javascript" src="./build.js"></script>
ES6 模块化规范
ES6 模块化规范是一个官方标准的规范,它是在语言标准的层面上实现了模块化功能,是目前最流行的模块化规范,且浏览器与服务端均支持该规范。
运行 ES6 模块
浏览器端可以直接运行,如在index.html页面中引入使用:<script type="module" src="./index.js"></script>
在 Node.js 中运行 ES6 模块代码有两种方式:
- 方式一:将js文件后缀从.js改为.mjs,Node会自动识别ES6模块
- 方式二:在package.json文件中设置type属性值为module
导出数据
ES6 模块化提供 3 种导出方式:分别导出、统一导出、默认导出。这3种导出方式,可以同时使用。
使用原则:导出的常量,务必用const定义。
分别导出:
// a.js 分别导出
export const name = '张三'
export function getTel() {
return '123456789'
}
统一导出:
// b.js 统一导出
const name = '李四'
function getTel() {
return '666666666'
}
export { name, getTel }
默认导出:
// c.js 默认导出
const name = '王五'
export const age = 25
function getTel() {
return '999999999'
}
export default { name, getTel }
导入数据
对于 ES6 模块化来说,使用何种导入方式,要根据导出方式决定。
「导入全部」(通用),可将模块中的所有导出内容整合到一个对象中。
// index.js
import * as a from './a.js'
console.log(a, a.getTel())
「命名导入」(对应导出方式:分别导出、统一导出)
// index.js 命名导入
import { name, getTel } from './a.js'
import { name as stuName, getTel as stuTel } from './a.js'
console.log(name, getTel())
console.log(stuName, stuTel())
「默认导入」(对应导出方式:默认导出)
// index.js 默认导入
import c from './c.js' // 默认导出的名字可以修改,如把c改为abc也行
console.log(c.name, c.getTel())
「命名导入 与 默认导入 可以混用」,且默认导入的内容必须放在前方。
// index.js 默认导入
import c, { age } from './c.js'
console.log(c.name, c.getTel(), age)
「动态导入」(通用),允许在运行时按需加载模块,返回值是一个Promise。
// index.js
const a = await import('./a.js')
console.log(a)
import可以不接收任何数据,如只让a.js参与运行:import './a.js'
。
- 转载请保留原文链接:JavaScript 模块化规范 https://aboss.top/post/817/
- 本站所有资源文章出自互联网收集整理,本站不参与制作,如果侵犯了您的合法权益,请联系本站我们会及时删除。
- 本站发布资源来源于互联网,可能存在水印或者引流等信息,请用户擦亮眼睛自行鉴别,做一个有主见和判断力的用户。
- 本站资源仅供研究、学习交流之用,若使用商业用途,请购买正版授权,否则产生的一切后果将由下载用户自行承担。
- 联系方式(#替换成@):mail#aboss.top
评论