模块化

本文围绕JavaScript模块化展开,介绍了CommonJS的模块引用、定义和表示,NodeJS中模块化的分类及加载步骤。对比了前端与服务端模块化的差异,提及AMD、CMD、UMD等规范。还阐述了ES6模块的export、import等特性,以及ES6和CommonJS在模块加载上的区别,最后提到webpack中的模块化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

commonJS

模块引用
var add = require('./add.js');
var config = require('config.js');
var http = require('http');
模块定义
module.exports.add = fucntion() {...}
module.exports = fucntion() {return ...}

一个文件代表一个模块,一个模块除了自己的函数作用域之外,最外成还有一个模块作用域,module 代表这个模块,exports 是 module 的属性。require() 也在这个模块的上下文中,用来引入外部模块。

模块表示

规范:

  • 必须是字符串
  • 可以是相对路径
  • 可以是绝对路径
  • 可以省略后缀名

NodeJS中模块化

一个文件是一个模块 —— module
一个模块就是一个 Module 实例
Node 中Module 的构造函数:

function Module(id, parent) {
	this.id = id;
	this.exports = {};
	this.parent = parent;
	if (parent && parent.children) {
		parent.children.push(this);
	}
	this.filename = null;
	this.loaded = false;
	this.children = [];
}
// 实例化一个模块
var module = new Module(filename, parent);
node 模块分类
Node模块
核心模块
文件模块
http/fs/path/Buffer
a.js/../b.js/express

node 模块的引入一般需要经过三个步骤:

  • 路径分析
  • 文件定位
  • 编译执行

核心模块会省略文件定位和编译执行这两部,加载速度比一般的模块更快。

前端模块化

前端模块化和服务端模块化的区别

  • 服务端加载模块从硬盘读取,消耗时间可以忽略
  • 浏览器需要先从服务器端下载这个文件,再用 commonJS 的require 方式加载模块,需要等下载完毕,并运行之后才能得到所需的API

commonJS 不适合前端模块的原因:
commonJS是同步加载的,如果遇到通过http请求的模块,会阻塞代码的执行。
因此现在前端都是使用异步模块加载。

AMD(asynchronous Module Definition) & RequireJS:
与commonJS 相比,就是可以异步加载模块,不会阻塞。
RequireJS —— AMD 规范的实现。

运行时加载:

  • CommonJS 和AMD模块都只能在运行时确定模块之间的依赖关系
  • require 一个模块的时候,模块会先被执行,并返回一个对象,这个对象是整体加载的。

CMD(common Module Definition) $ seajs
CMD:通用模块规范
SeaJS:CMD的实现
CMD 与AMD 的主要区别在于定义模块和依赖引入部分。AMD需要在声明模块的时候指定所有的依赖,通过形参传递到模块内容中:

// AMD
defien(['dep1', 'dep2'], function(dep1, dep2) {
	return function(){};
})

// CDM
defin(factory);

CMD支持动态引入,require, exports 和 module 通过形参传递给模块,在需要依赖模块式,随时调用require() 引入

UMD(universal Module Definition)

ES6的模块

ES6 在语言层面实现了模块功能,是编译时加载。

export
export var name = 'xxx';
export function foo(x, y) {};

// 常用
const name = 'xxx';
const age = 18;
export {name, age};

// as 可以将一个模块输出多次
const s = 1;
export {s as t, s as m};
import
import {name, age} from './a.js';
import {name as personName} from './a.js';

// person.js
export name = 'xxx';
export age = 18;

// 逐一加载
import {name, age} from './person.js';
// 整体加载
import * as person from './person.js';
person.name;
person.age;

import 具有变量提升的特性,可以提前访问

export default

使用 export default 命令是, import 不需要加 { }。不使用 export default 时,import 必须加 { }

// person.js
export function getName() {}

import {getName} from ''
------
// person.js
export default function getName() {}

import getName from './person.js'

export default 其实是导出一个叫做 default 的变量,所以后面不能再跟变量声明语句。
可以同时使用 export 和 export default

// person.js
export name = 'xxx';
export default function getName() {}

import getName, {name} from './person.js'

ES6 和 commonJS 在模块加载上的区别

// ES6  编译时加载,只加载 path 模块的3个方法,其他不加载
// 遇到import 时生成一个动态的只读引用,当真正需要的时候再到模块里取值,所以ES6 的模块是动态引用,且不会缓存。
import {basename, direname, parse} from 'path';

// commonJs 在运行时,将path运行一遍,返回一个对象,并将这个对象缓存起来,以后的加载都是读取这个缓存值。
let {basename, dirname, parse} = require('path');

因为 CommonJS 输出的是值的拷贝,所以当模块中的值在引用之后改变时,不会影响到输出结果。


webpack 中的模块化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值