js中的模块,面试补课(1)

153 阅读1分钟

前端模块化

CommonJS

// math.js
function add (a,b){
    return a + b;
}
module.exports =  {
    add,
};
// logic.js
const { add } = require('./math');
add(2,3);

ES6 Module

// math.js
const add = (a,b) =>{
    return a + b;
};
const minus = (a,b) =>{
    return a - b;
}
export default add;
export { add,minus };
// logic.js
import { minus, /* add */ } from './math';
import add from './math';
add(2,3);

两者的比较:

  • 1、require运行时同步加载,import编译时前置加载
  • 2、require会缓存用到的模块,import则不会
  • 3、require是值拷贝,import是值引用,如果导出的值使用了对应模块内部变化可能会影响到import出的值的变化,可以通过在模块内部使用setTimeout改变值,并且导出这个值进行验证

node是用的是commonjs,虽然现在实验性的加入了ES6 Module需要在package.json中写上

{
  "type":"module"
}
node --experimental-moduels index.js

在服务器端,模块文件存在本地磁盘或者内存缓存中,读取速度非常快。在浏览器端由于网络的限制,更合理的方案是采用异步加载

AMD和require.js

AMD规范采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调中,等加载完成后,回调才会运行。

<!-- 首先引入require.js以及入口文件main.js,main.js中配置require.config规定项目中用到的基础模块 -->
<script src="./require.js" data-main="./main.js"></script>
// main.js 入口文件
require.config({
    baseUrl:'js/lib',
    paths:{ // 依赖前置
        'jquery':'jquery.min.js', // 去./js/lib/juery.min.js
    }
});
require(['jquery'],$ => {
    // doSomething
})

// 在AMD中如果定义的某个模块需要引用其他模块

// math.js 这是一个没有其余依赖的自定义模块
define(() => {
    const add = (a,b) =>{
        return a + b;
    };
    return {
        add,
    };
});
// 该模块依赖于jquery
define(['jquery','math'],($,math) => {
    $('#app').textContent = `${ math.add(1,2) }`;
});

CMD和sea.js

// math.js
define((require,exports,module)=>{
    const a = require('./a'); //依赖就近
    a.doSomething();
});
// 加载模块
seajs.use(['math.js'],(math)=>{
    // doSomething
})

两者的比较:

  • AMD推崇依赖前置,require.config即可看出
  • CMD推崇依赖就近,在做自定义模块时,依赖另一模块时可以看出