生活随笔
收集整理的這篇文章主要介紹了
【重要】ES6-23 JavaScript模块化
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
- 前端js模塊化的演變發(fā)展
- 模塊化解決的問題
- 傳統(tǒng)模塊化、插件化
- CommonJS
- AMD/CMD
- ES6模塊化
ES6以前 沒有js引擎
一開始js寫在html的script標(biāo)簽里js內(nèi)容增多,抽取出index.js文件,外部引入js再增加,index.html對應(yīng)index.js index2.html對應(yīng)index2.js(模塊化概念的誕生)含有可復(fù)用的代碼,提出公共的common.js引入common.js的所有內(nèi)容不合理 → 不能光以頁面為基準(zhǔn)來區(qū)分程序塊、分js文件
案例一 模塊化初試
<!DOCTYPE html
>
<html lang
="en">
<head
><meta charset
="UTF-8"><meta http
-equiv
="X-UA-Compatible" content
="IE=edge"><meta name
="viewport" content
="width=device-width, initial-scale=1.0"><title
>Document
</title
>
</head
>
<body
><script type
="text/javascript" src
="js/module_a.js"></script
><script type
="text/javascript" src
="js/module_b.js"></script
><script type
="text/javascript" src
="js/module_c.js"></script
><script type
="text/javascript" src
="js/index.js"></script
>
</body
>
</html
>
var a
= [1, 2, 3, 4, 5].reverse()
var b
= a
.concat([6, 7, 8, 9, 10])
var c
= b
.join('-')
console
.log(a
)
console
.log(b
)
console
.log(c
)
存在問題
- js引擎遇到script時(shí)阻塞,所以這4個(gè)js文件必須按內(nèi)部的邏輯,順序加載,順序是不能變的
- 這4個(gè)文件共用了JS作用域-全局作用域
- 因此:污染全局 + if 變量重名 → 變量覆蓋
模塊化解決問題:
加載順序污染全局
案例二 IIFE注入
歷史問題:ECMA規(guī)定語句應(yīng)當(dāng)以分號結(jié)尾,早前js都是運(yùn)行在瀏覽器上的,但瀏覽器支持判斷當(dāng)前是否是語句,是就自動(dòng)加上分號。當(dāng)使用多個(gè)IIFE,且不寫分號時(shí),瀏覽器無法識別,報(bào)錯(cuò)。因此約定俗成的規(guī)定,IIFE前面必須寫分號,更規(guī)范的是結(jié)尾也寫分號,即
;(function(){
})();
使用IIFE,解決污染全局,為了易于拓展,模塊應(yīng)當(dāng)返回對象新的問題,若沒有拋到全局,如何在模塊之間獲得相應(yīng)的abc用變量接收IIFE的返回值,在需要用的的模塊傳入(注入),解決了模塊依賴注意:模塊名完全獨(dú)立,不應(yīng)該重復(fù),因此在全局聲明了,而內(nèi)部abc屬于數(shù)據(jù)類型的變量,不能在全局聲明注意:不注入moduleABC,直接用moduleA.a訪問變量能得到正確結(jié)果,但注入意味著moduleABC被引入到局部作用域下,不再需要去全局上查找了
var moduleA
= (function () {var a
= [1, 2, 3, 4, 5].reverse()return {a
: a
}
})();
var moduleB
= (function (moduleA) {var b
= moduleA
.a
.concat([6, 7, 8, 9, 10])return {b
: b
}
})(moduleA
);
var moduleC
= (function (moduleB) {var c
= moduleB
.b
.join('-')return {c
: c
}
})(moduleB
);
; (function (moduleA, moduleB, moduleC) {console
.log(moduleA
.a
)console
.log(moduleB
.b
)console
.log(moduleC
.c
)
})(moduleA
, moduleB
, moduleC
);
存在問題
順序問題依然未解決
插件
構(gòu)造函數(shù)執(zhí)行init構(gòu)造函數(shù)掛載到window(插件)script里實(shí)例化
案例三 CommonJS
NodeJS誕生帶來了前所未有的模塊化體驗(yàn)
require(...) 引入模塊
module.exports導(dǎo)出模塊
運(yùn)行在node環(huán)境下
CommonJS是模塊化規(guī)范,來源于NodeJS
在服務(wù)端開發(fā),引入模塊用require,是同步的方法
只要引用,就會(huì)創(chuàng)建模塊的實(shí)例
有非常強(qiáng)的緩存機(jī)制
一定是在Node上運(yùn)行,客戶端運(yùn)行不了(要借助webpack?)
require實(shí)質(zhì)是IIFE,會(huì)傳入一些參數(shù)
(function(exports,require,module,__filename.__dirname){})()
<!DOCTYPE html
>
<html lang
="en">
<head
><meta charset
="UTF-8"><meta http
-equiv
="X-UA-Compatible" content
="IE=edge"><meta name
="viewport" content
="width=device-width, initial-scale=1.0"><title
>Document
</title
>
</head
>
<body
><script type
="text/javascript" src
="index.js"></script
>
</body
>
</html
>
var a
= (function () {return [1, 2, 3, 4, 5].reverse()
})();
module
.exports
= {a
};
var moduleA
= require('./module_a')
var b
= (function () {return moduleA
.a
.concat([6, 7, 8, 9, 10])
})();
module
.exports
= {b
}
var moduleB
= require('./module_b')
var c
= (function () {return moduleB
.b
.join('-')
})();
module
.exports
= {c
: c
}
var moduleA
= require('./js/module_a.js');
var moduleB
= require('./js/module_b.js');
var moduleC
= require('./js/module_c.js');
; (function () {console
.log(moduleA
.a
)console
.log(moduleB
.b
)console
.log(moduleC
.c
)
})()
案例四 AMD
- 不需要借助webpack就能運(yùn)行在客戶端
- 所有依賴加載完成后才會(huì)執(zhí)行回調(diào)函數(shù)(前置依賴)
AMD Asynchronous Module Definition 異步模塊定義
來源于CommonJS
define(moduleName, [module], factory) 定義模塊
require([module], callback) 引入模塊
RequireJS實(shí)現(xiàn)AMD
引入require.js定義+使用依賴時(shí)注入使用module得先require.config配置路徑
<!DOCTYPE html
>
<html lang
="en">
<head
><meta charset
="UTF-8"><meta http
-equiv
="X-UA-Compatible" content
="IE=edge"><meta name
="viewport" content
="width=device-width, initial-scale=1.0"><title
>Document
</title
>
</head
>
<body
><script src
="js/require.js"></script
><script src
="js/index.js"></script
>
</body
>
</html
>
define('moduleA', function () {var a
= [[1, 2, 3, 4, 5]]return {a
: a
.reverse()}
})
define('moduleB', ['moduleA'], function (moduleA) {return {b
: moduleA
.a
.concat([6, 7, 8, 9, 10])}
})
define('moduleC', ['moduleB'], function (moduleB) {return {c
: moduleB
.b
.join('-')}
})
require
.config({paths
: {moduleA
: 'js/module_a',moduleB
: 'js/module_b',moduleC
: 'js/module_c'}
})
require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC) {console
.log(moduleA
.a
)console
.log(moduleB
.b
)console
.log(moduleC
.c
)
});
案例五CMD
- 阿里對模塊化的貢獻(xiàn)
- require加載 define定義
- exports導(dǎo)出(return和它的效果一直) module操作
- 需要配置模塊URL
- 依賴加載完畢后執(zhí)行factory
- 依賴就近 按需加載(這是和CommonJS AMD本質(zhì)上的不同)
Common Mudule Definition 通用模塊定義
define(function(require,exports,module){}) 定義模塊
seajs.use([module路徑],function(moduleA,moduleB,moduleC){}) 使用模塊
<!DOCTYPE html
>
<html lang
="en">
<head
><meta charset
="UTF-8"><meta http
-equiv
="X-UA-Compatible" content
="IE=edge"><meta name
="viewport" content
="width=device-width, initial-scale=1.0"><title
>Document
</title
>
</head
>
<body
><script src
="js/sea.js"></script
><script src
="js/index.js"></script
>
</body
>
</html
>
define(function (require, exports, module) {var a
= [[1, 2, 3, 4, 5]]return {a
: a
.reverse()}
})
define(function (require, exports, module) {var moduleA
= require('module_a')return {b
: moduleA
.a
.concat([6, 7, 8, 9, 10])}
})
define(function (require, exports, module) {var moduleB
= require('module_b')return {c
: moduleB
.b
.join('-')}
})
seajs
.use(['module_a.js', 'module_b.js', 'module_c.js'], function (moduleA, moduleB, moduleC) {console
.log(moduleA
.a
)console
.log(moduleB
.b
)console
.log(moduleC
.c
)
})
案例六 ES6模塊化規(guī)范
import module from ‘模塊路徑’ 導(dǎo)入模塊
export module 導(dǎo)出模塊
Uncaught SyntaxError: Cannot use import statement outside a module
調(diào)試過程中的報(bào)錯(cuò)解答
<!DOCTYPE html
>
<html lang
="en">
<head
><meta charset
="UTF-8"><meta http
-equiv
="X-UA-Compatible" content
="IE=edge"><meta name
="viewport" content
="width=device-width, initial-scale=1.0"><title
>Document
</title
>
</head
>
<body
><script type
="module" src
="./js/index.js"></script
>
</body
>
</html
>
export default {a
: [1, 2, 3, 4, 5].reverse()
}
import moduleA
from './module_a.js'
export default {b
: moduleA
.a
.concat([6, 7, 8, 9, 10])
}
import moduleB
from './module_b.js'
export default {c
: moduleB
.b
.join('-')
}
import moduleA
from './module_a.js'
import moduleB
from './module_b.js'
import moduleC
from './module_c.js'; (function (moduleA, moduleB, moduleC) {console
.log(moduleA
.a
)console
.log(moduleB
.b
)console
.log(moduleC
.c
)
})(moduleA
, moduleB
, moduleC
);
案例7 CommonJS與ES6的區(qū)別
exports
.a
= 0;
setTimeout(() => {console
.log('來自export', ++exports
.a
)
}, 300);
const { a
} = require('./export')
setTimeout(() => {console
.log('來自commonjs', a
)
}, 300);
import { a
} from './export'
setTimeout(() => {console
.log('來自es6', a
)
}, 300);
commonjs輸出的是一個(gè)值的拷貝es6模塊輸出的是值的引用commonjs模塊是在運(yùn)行時(shí)加載(commonjs運(yùn)行在服務(wù)端,require時(shí)加載)es6模塊是在編譯時(shí)加載
YUI
總結(jié)
以上是生活随笔為你收集整理的【重要】ES6-23 JavaScript模块化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。