Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

前端模块化 #9

Open
sihai00 opened this issue Jul 23, 2019 · 0 comments
Open

前端模块化 #9

sihai00 opened this issue Jul 23, 2019 · 0 comments
Assignees

Comments

@sihai00
Copy link
Owner

sihai00 commented Jul 23, 2019

作用

模块化主要是用来抽离公共代码,隔离作用域,避免变量冲突等

IIFE 自执行函数。

(function(){
  return {
	data:[]
  }
})()

AMD

使用requireJS 来编写模块化。特点:依赖前置。初始化时加载完成所有模块,且执行所有模块。

define('./index.js', function(code){
	// code 就是index.js 返回的内容
})

CMD

使用seaJS 来编写模块化。特点:就近依赖,初始化时加载完成所有模块,require时再执行。

define(function(require, exports, module) {  
  var indexCode = require('./index.js');
});

CommonJS

nodejs 中自带的模块化。

  • 输出:common 输出的是一个值的拷贝。模块可以多次加载,但是只会在第一次加载时运行一次,结果被缓存,再加载直接读取缓存结果。
  • 加载方式:common 运行时加载。因为 CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成
// 循环加载例子
// a.js
exports.x = 'a1';
console.log('a.js ', require('./b.js').x);
exports.x = 'a2';

//b.js
exports.x = 'b1';
console.log('b.js ', require('./a.js').x);
exports.x = 'b2';

//main
console.log('index.js', require('./a.js').x);

// 输出
b.js  a1
a.js  b2
index.js  a2

结果如下:

1、a.js准备加载,在内存中生成module对象moduleA
2、a.js执行exports.x = 'a1'; 在moduleA的exports属性中添加x
3、a.js执行console.log('a.js', require('./b.js').x); 检测到require关键字,开始加载b.js,a.js执行暂停
4、b.js准备加载,在内存中生成module对象moduleB
5、b.js执行exports.x = 'b1'; 在moduleB的exports属性中添加x
6、b.js执行console.log('b.js', require('./a.js').x); 检测到require关键字,开始加载a.js,b.js执行暂停
7、检测到内存中存在a.js的module对象moduleA,于是可以将第6步看成console.log('b.js', moduleA.x); 在第二步中moduleA.x赋值为a1,于是输出b.js, a1
8、b.js继续执行,exports.x = 'b2',改写moduleBexports的x属性
9、b.js执行完成,回到a.js,此时同理可以将第3步看成console.log('a.js', modulerB.x); 输出了a.js, b2
10、a.js继续执行,改写exports.x = 'a2'
11、输出index.js a2

UMD

兼容AMD,CommonJS 模块化语法。即 UMD = AMD + CommonJS

ES6 Modules

异步加载

  • 输出:es6输出的是一个值的引用。ES6 模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。
  • 加载方式:es6 编译时输出接口。ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。
// 值拷贝 vs 引用

// CommonJS
let a = 1;
exports.a = a;
exports.add = () => {
    a++;
};

const { add, a } = require('./a.js');
add();
console.log(a); // 1

// ES6
export const a = 1;
export const add = () => {
    a++;
};

import { a, add } from './a.js';
add();
console.log(a); // 2
// 显而易见CommonJS和ES6之间,值拷贝和引用的区别吧。

参考

第 26 题: 前端中的模块化开发
WEB 前端模块化都有什么?
Module 的加载实现

@sihai00 sihai00 self-assigned this Jul 23, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant