在做项目的时候越来越发现模块化的重要性,做好模块化开发不仅给后期的维护带来不少好处而且大大提升项目开发效率,接下来整理一下模块化相关知识吧。
模块化开发的优点
- 封装方法、提高代码的复用性、可维护性和可读性
- 隔离作用域,避免污染全局作用域
- 避免变量冲突
模块化开发的各种方法
立即执行函数(IIFE)
- 立即执行函数来创建模块,将私有成员放在函数作用域以内,不暴露在外部。将公共的方法返回。
var module = (function() {
var privateVar = 'Private Variable';
function privateMethod() {
console.log('This is a private method');
}
function publicMethod() {
console.log('This is a public method');
}
return {
publicMethod: publicMethod
};
})();
module.publicMethod(); // Output: This is a public method
CommonJS:
- node中自带的,同步使用require导入模块,module.exports或exports导出模块,适用于服务器端。
// math.js
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
module.exports = {
add,
subtract
};
// app.js
const math = require('./math');
console.log(math.add(2, 3)); // Output: 5
console.log(math.subtract(5, 2)); // Output: 3
AMD(Asynchronous Module Definition)
- 使用define定义模块,异步加载模块,适用于浏览器、按需加载模块
// math.js
define([], function() {
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
return {
add,
subtract
};
});
// app.js
require(['math'], function(math) {
console.log(math.add(2, 3)); // Output: 5
console.log(math.subtract(5, 2)); // Output: 3
});
CMD
- 使用define定义模块,异步加载模块,适用于浏览器、就近依赖
define(function(require, exports) {
// 对外提供name属性
exports.name = 'myModule';
// 对外提供hello方法
exports.hello = function() {
console.log('Hello myModule');
};
});
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="sea.js"></script>
<script type="text/javascript">
//加载一个模块,在加载完成时,执行回调
seajs.use('myModule', function(a) {
console.log(a.name);
a.hello();
});
</script>
</head>
<body>
</body>
</html>
ES6模块
- 使用
import
导入模块,使用export
导出模块,浏览器与服务器通用
// math.js
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
// app.js
import { add, subtract } from './math';
console.log(add(2, 3)); // Output: 5
console.log(subtract(5, 2)); // Output: 3
异步加载JS有哪些方法
1 设置<script>属性async = 'async'
- 脚本将异步加载并立即执行,不会阻塞页面的解析和渲染、加载完成后,将在页面任何位置执行
<script src='script.js' async="async"><script>
2 动态创建script DOM:
-
使用JS动态创建<script>元素,通过设置src属性指定脚本的URL,
var script = document.creatElement('script');
script.src = 'script.js';
document.head.appendChild(script)
3 defer属性
<script src="script.js" defer></script>
4 XmlHttpRequest脚本注入
-
利用对象加载脚本内容,将其注入到页面当中,使用eval()函数执行脚本。
var xhr = new XMLHttpRequest();
xhr.open('GET','script.js',true);
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status === 200){
eval(xhr.responseText);
}
};
xhr.send();
5 异步加载库LABjs
- LABjs是一个异步加载JS的库,可以控制JS的加载顺序,可用它来的API定义和加载依赖关系。
$LAB
.script('A.js')
.wait()
.script('B.js')
6 模块加载器 Sea.js
- 用于web端模块化开发的加载器,可以异步加载和管理模块,加载完成后执行回调函数。
seajs.use(['module1','module2'],function(module1,module2){
console.log('Hello')
});
7 Dederred Scripts(延迟脚本):
- defer属性可以将脚本延迟到文档解析之后再执行,并且会按照他们在文档中出现的顺序执行,但在DOMContentLoaded事件触发之前执行。
<script src="script.js" defer></script>
8 Dynamic Import(动态导入):
- import()可以异步加载JS模块,并返回一个Promise对象,链式调用
import('module.js')
.then(module => {
// 执行模块加载完成后的逻辑
})
.catch(error => {
// 处理加载失败的情况
});
9 Web Workers(Web工作者)
- Web Workers运行在后台的JS脚本,可以耗时操作而不会阻塞主线程。
- 可以异步加载和执行JS脚本,提高页面的响应性
var worker = new Worker('worker.js');
worker.onmessage = function(event) {
// 处理从 Worker 返回的消息
};
worker.postMessage('start');
参考文章
前端进阶之旅
第25题 谈谈模块化的发展历程以及各自的特_请定义一个文件模块mymodule.js,定义一个name变量及一个sayhello的方法,暴露_crazy的蓝色梦想的博客-CSDN博客