模块化开发
1. 模块化开发最终的目的是将程序划分成
一个个小的结构
。
2. 这个结构中编写属于
自己的逻辑代码
,有
自己的作用域
,定义变量名词时不会影响到其他的结构。
3. 这个结构可以将自己希望暴露的
变量、函数、对象等导出
给其结构使用,
也可以通过某种方式,
导入
另外结构中的
变量、函数、对象
等。
早期没有模块化
没有模块化带来了很多的问题:比如命名冲突问题,立即函数调用表达式解决这个问题。
const moduleA = (function () {
let name = "lisi";
let age = 18;
return {
name,
age,
};
}());
缺点:
1. 每个文件中的代码都需要包裹在一个匿名函数中来编写
2. 可能出现模块名称相同的情况
CommonJS
CommonJS规范的核心变量
:
exports、module.exports、require
1. exports和module.exports
可以负责
对模块中的内容进行导出
2. require函数
可以帮助我们
导入其他模块(自定义模块、系统模块、第三方库模块)中的内容
exports导出
exports是一个对象,我们可以在这个对象中添加很多个属性,添加的属性会导出。
const UTIL_NAME = "lisi";
function add(a, b) {
return a + b;
}
exports.UTIL_NAME = UTIL_NAME;
exports.add = add;
引入:
const aaa = require("./aaa.js");
console.log(aaa.UTIL_NAME);
console.log(aaa.add(1, 2));
如果在 引入方 修改 aaa 对象的属性,在 导出方 也会修改。
引入方:
const aaa = require("./aaa.js");
console.log(aaa.UTIL_NAME);
aaa.UTIL_NAME = "zhangsan";
导出方:
const UTIL_NAME = "lisi";
exports.UTIL_NAME = UTIL_NAME;
setTimeout(() => {
console.log(exports.UTIL_NAME);
}, 2000);
效果:
原理:
共同修改一块内存。
module.exports导出
module才是导出的真正实现者
const name = "lisi";
console.log(exports == module.exports); // true
module.exports = {
name: "zhangsan",
};
exports.name = "wangwu";
===============================================
const aaa = require("./aaa.js");
console.log(aaa.name); // zhangsan
const name = "lisi";
console.log(exports == module.exports); //true
exports = {
name: "zhangsan",
};
module.exports.name = "wangwu";
==============================================
const aaa = require("./aaa.js");
console.log(aaa.name); // wangwu
所以,require 的本质是在找 module.exports 对象。
内存图:
CommonJS规范缺点
CommonJS加载模块是同步的,只有
等到对应的模块加载完毕
,
当前模块中的内容才能被运行,
如果将它应用于浏览器,
浏览器
加载js文件需要先从服务器将文件下载下来
,之后
再加载运行,
那么采用
同步的就意味着后续的js代码都无法正常运行
,即使是
一些简单的DOM操作
。
ES Module
ES Module 和 CommonJS 的差异
1.
使用了
import
和
export
关键字,
export
负责将模块内的内容
导出,
import
负责从其他模块
导入
内容。
2. 采用
编译期的静态分析
,并且也
加入了动态引用的方式
使用方式:
1. 常规用法:
const name = "lisi";
const age = 18;
function sayHello() {
console.log("hello");
}
export { name, age, sayHello };
导入:
import { name, age, sayHello } from "./aaa";
2. 导出时,起别名
const name = "lisi";
const age = 18;
function sayHello() {
console.log("hello");
}
export { name as fname, age, sayHello };
导入时,起别名
import { name as fname, age, sayHello } from "./aaa";
3. * 导入
import * as foo from "./aaa";
console.log(foo.name);
console.log(foo.age);
foo.sayHello();
default用法(默认导出)
默认导出export时可以不需要指定名字,导入时不需要使用 {},并且可以自己来指定名字,在一个模块中,只能有一个默认导出(default export)
function sayHello() {
console.log("hello");
}
export default sayHello;
============================== 使用
import fun from "./aaa";
fun();
import函数
动态加载某一个模块,import函数返回一个Promise,可以通过then获取结果