JavaScript 模块化

JavaScript 模块化

image.png

JavaScript 的历史问题

背景

JavaScript 在一开始诞生的时候只是用来网页脚本的开发,其实没有模块化和命名空间的概念。

JS 的模块化需求日益增长。

幼年期:无模块化

模块化思维的萌芽。

  1. 需要在页面中加载不同的 js:动画库,表单库,格式化工具
  2. 多种 js 文件被分在了不同的文件中
  3. 不同的文件又被同一个模版所引入

我们的解决方案是,在一个 html 中,引入不同的 script,这样实现了一个模版引入多个不同的 js。

这个其实也是有意义的,可以认为是 js 模块化的第一步。

这里补充一下 script 标签的三个参数:

  • normal:遇到标签,停止往下解析,下载且执行 JavaScript
  • async:解析到标签开始异步下载,下载完之后立即执行,并且会阻塞渲染,然后继续执行
  • defer:解析到标签开始异步下载,继续解析

(分别对应:normal,defer,async)

image.png

依然存在的问题:

  • 兼容性
  • 问题方向:浏览器渲染原理、同步异步原理、模块化加载原理
  • 污染全局作用域:不易于大型项目的开发和多人项目的合作

image.png

成长期:模块化初心 IIFE

作用域的把控
let count = 0

const increase = () => {
	count++
}

const rest = () => {
	count = 0
}

increase()
rest()

(
	// 利用立即执行行数
	() => {
		let count = 0

		const increase = () => {
			count++
		}

		const rest = () => {
			count = 0
		}

		increase()
		rest()
	}
)()

这样我们使用了 IIFE module 实现了模块和外部之间的隔离。

成熟期

CJS - commonjs

nodejs 制定的标准。

  • 特征:通过 module + export 去对外暴露接口
  • 通过 require 去调用其他的模块,同步加载

模块组织方式:

main.js

// 引入部分
const dependecyModule1 = require('./dependecyModule1')
const dependecyModule2 = require('./dependecyModule2')

// 核心逻辑
let count = 0
const increase = () => count++
const reset = () => count = 0

// 暴露接口部分
export.increase = increase
export.reset = reset

// 或者统一暴露
module.exports = {
	increase,reset
}

使用

const {increase, reset} = require('main.js')

commonjs 为每一个模块提供了一个 exports 变量,指向 module.exports,相当于在每一个模块代码的头部写了一行:

var exports = module.exports

exports 和 module.exports 指向同一个内存空间,module.exports 是真正的暴露对象。exports 是 module.exports 对象的引用。

commonjs 的特点:

  • 使用同步加载的方式,适用于服务端,因为服务端的代码阻塞用户无法感知,而前端的阻塞会非常影响体验
  • 所有的代码都运行在某块作用域中,不会影响全局
  • 模块可以多次加载,但是只是第一次会下载,后面用的都是缓存
  • 模块加载的顺序就是代码出现的顺序

AMD(Asynchronous Module Definition)

采用异步加载的方式加载模块,模块的加载不影响后面语句的运行,所有依赖这个模块的语句都会被写在一个回调函数中,等待加载完成之后,这个回调函数才会执行。

最热门的一个库就是 require.js,它是一个 JavaScript 模块化框架。

requirejs(["helper/util"], function(util) {
    //This function is called when scripts/helper/util.js is loaded.
    //If util.js calls define(), then this function is not fired until
    //util's dependencies have loaded, and the util argument will hold
    //the module value for "helper/util".
});

CMD(Common Module Definition)

通用加载模块

常见的库就是 sea.js

UMD(Universal Module Definition)

UMD是AMD和CommonJS的糅合。

UMD的实现很简单:

  • 先判断是否支持Node.js模块(exports是否存在),存在则使用Node.js模块模式。
  • 再判断是否支持AMD(define是否存在),存在则使用AMD方式加载模块。
  • 前两个都不存在,则将模块公开到全局(window或global)。

ES6 模块化

编译时去顶模块的依赖关系,原生支持。

  • 21
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

城南顾北

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值