javascript-modules

109 阅读2分钟

看过很多片段讲解es6的module功能,import、export、export default用起来还是一知半解。

关键词:运行时加载、编译时加载

最开始写的js

到处都是全局变量和方法,容易重名。

// index.js
var attr1 = '全局变量1';
var attr2 = '全局变量2';
function fn1() {};
function fn2() {};

命名空间方式

为了避免重名问题衍生,命名空间的模式,全局暴露一个对象把方法和属性存在这个对象里面。

var scopeObj = {
    attr: '变量',
    fn(){console.log('yes!')},
}
console.log(scopeObj.attr);  // 变量
scopeObj.fn();  // yes!

// 不安全,被直接修改属性和方法
scopeObj.attr = '我被修改了'
scopeObj.fn = function () {
    console.log('no!')
}
console.log(scopeObj.attr);  // 我被修改了
scopeObj.fn();  // no!

IIFE 函数自执行方式

(function(win){
    function fn1() {
        console.log('方法1')
    }
    function fn2() {
        console.log('方法2')
    }
    win.fns = {fn1, fn2}
    // 可调用
    fns.fn1(); // 方法1
    // 覆盖方法,单不能修改原有定义
    fns.fn1 = function () {
        console.log('方法3');
    }
    win.fns2 = {fn1, fn2}
    fns.fn1(); // 方法3
    // 照常输入
    fns2.fn1(); // 方法1
})(window)

// 依赖第三方插件情况,讲究引入先后顺序功能复杂理不清依赖先后顺序
// 引用交叉问题:假设c.js依赖b.js, b.js依赖a.js, 没有把a.js加上就导致了引用报undefined错误
(function(win, $){
    function fn() {
        var app = $('#app')
    }
    win.myFuns = {fn}
})(window, jQuery)


// index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <!-- 函数自执行模式 -->
    <script src="./a.js"></script>
    <script src="./b.js"></script>
    <script src="./c.js"></script>
</head>
<body>
    
</body>
</html>
// a.js
// b.js
// c.js

AMD\CMD\UMD\CommonJS\ES Modules

CommonJS

module.export、require

// 导出
function sayNo(){console.log('no!')}
function sayHello(){console.log('hi!')}
module.export = {
    sayNo: sayNo,
    sayHello: sayHello
}
// 导入
const say = require('./hello.js')
say.sayNo()
AMD (require.js)

define、require

// 模块定义
define(function(){
    return {name: 'miki'}
})
// 模块依赖其他模块, 第一个参数为依赖模块数组方式
define(['jquery'], function($){
    return {name: 'miki'}
})
// 引用模块
require(['jquery', 'monent'], function($, monent){
    var app = $('#app')
})
CMD (sea.js)

define、exports、seajs.use

// 模块定义
define(function(require, exports, module){
    var $ = require('jquery')
    var say = function(){console.log('hello world!')}
    exports.say = say
})
// 模块引用
// 这个使用方式和AMD的模块引用差别在关键字?
seajs.use(['say.js'], function(sayFn){
    sayFn.say()
})
ES6 Module

export、export default、import

// 必须配对关系方法或者值必须放在变量里
var a = '1'
var b = functon(){}
export {
    a: a,
    b: b
}
// 使用
import {a, b} from './test.js'

// 使用export default导出的模块使用可以省略花括号
export default {a, b}
import test from './test.js'

// 为import模块重新命名(防止两个模块中命名冲突)
import test as test1 from './test.js'
import {a as a1, b as b1} from './test.js'
疑问
// 脑壳疼为啥会有后面的default嘛
const x = require('xx').default