随着js复杂度的提高,模块化更是应用广泛,那有没有小伙伴对各种引入导出傻傻分不清楚?module.export跟exports 有啥区别?
前言 - 模块化
通常我们在编写代码时,会将复杂的问题根据实际情况进行合理的拆分,让代码更具备可读性与可维护性。因此一个模块可以理解为整体的一部分。
- 每个模块都是独立的个体,当然最好是遵循最小功能模块化;
- 模块是复用的
- 更好的分离,可按需加载
模块化的发展
1.最简单的全局函数
function fn1(){
}
function fn2(){
}
实现: 每个函数按照功能划分
问题: 全局污染,应该偏向面向过程的开发模式
2.namespace模式 : 对象字面量的写法,对某个功能块简单的封装
let action = {
name: 'aa',
printName(){
console.log(this.name)
}
}
action.name = 'bb'
action.printName()//bb
实现: 可以封装比较复杂的组件方法,减少了全局变量
问题; 里面的方法数据是可以改变的。数据不安全
3.IIFE模式:匿名函数自调用(闭包)
jquery的源码就是用的这个模式;也包括jq的一些组件,都是这样处理。
实现: 将数据和行为封装到一个函数内部, 通过给window添加属性来向外暴露接口,避免全局变量污染
模块化规范
1.Common js
概述
node js 采用的是Common js规范。每个js都是单独的模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。在服务器端,模块的加载是运行时同步加载的;在浏览器端,模块需要提前编译打包处理。
特点
1.有自己的作用域,不会污染全局
2.文件里的内容是私有的,保证数据安全
3.模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
4.模块加载的顺序,跟代码的顺序相关(同步加载~)
语法
//导出
module.exports = value
exports.xxx = value
//引入
require()
加载机制
CommonJS模块的加载机制是,输入的是被输出的值的拷贝。也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。
2.AMD
AMD和CMD都是异步的,应用于浏览器端的。因为是异步的,所以在加载完成后,可以用回调访问数据方法。
define(['module1', 'module2'], function(m1, m2){
return 模块
})
require(['module1', 'module2'], function(m1, m2){
使用m1/m2
})
3.CMD
跟AMD一样都是异步的,CMD规范整合了CommonJS和AMD规范的特点,在sea.js 中,遵循的是CMD规范。
define(function(require, exports, module){
exports.xxx = value
module.exports = value
})
define(function (require) {
var m1 = require('./module1')
var m4 = require('./module4')
m1.show()
m4.show()
})
4.ES6的模块化
ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。
// CommonJS模块
let { stat, exists, readFile } = require('fs');
// 等同于
let _fs = require('fs');
let stat = _fs.stat;
let exists = _fs.exists;
let readfile = _fs.readfile;
// ES6模块
import { stat, exists, readFile } from 'fs';
commonjs的实质是整体加载fs模块(即加载fs的所有方法),生成一个对象(_fs),然后再从这个对象上面读取 3 个方法。这种加载称为“运行时加载”,因为只有运行时才能得到这个对象,导致完全没办法在编译时做“静态优化”。
ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。
ES6 模块的实质是从fs模块加载 3 个方法,其他方法不加载。这种加载称为“编译时加载”或者静态加载,即 ES6 可以在编译时就完成模块加载,效率要比 CommonJS 模块的加载方式高
两者的区别:
① CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
② CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。