模塊的概念javascript
一個複雜的項目開發中,會寫不少js文件,一個js文件執行某些特定的功能,那麼每一個js均可以稱爲一個模塊,這就是模塊的概念css
每一個js模塊內部數據/實現是私有的, 只是向外部暴露一些接口(方法)與外部其它模塊通訊html
模塊化的進化史前端
全局function模式:將不一樣的功能封裝成不一樣的全局函數java
問題: Global被污染了, 很容易引發命名衝突jquery
//數據 let data = 'atguigu.com' //操做數據的函數 function foo() { console.log(`foo() ${data}`) } function bar() { console.log(`bar() ${data}`) }
let data2 = 'other data'; function foo() { //與另外一個模塊中的函數衝突了 console.log(`foo() ${data2}`) }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>01_全局function模式</title> </head> <body> <script type='text/javascript' src='module1.js'></script> <script type='text/javascript' src='module2.js'></script> <script type='text/javascript'> let data = "修改後的數據" // 模塊1中已經定義了data變量,重複定義同名變量報錯 foo() // module2模塊中的foo()方法覆蓋了module1模塊中的foo()方法 bar() </script> </body> </html>
namespace模式程序員
簡單對象封裝,減小了全局變量
問題: 不安全(數據不是私有的, 外部能夠直接修改)express
let myModule1 = { data: 'atguigu.com', foo() { console.log(`foo() ${this.data}`) }, bar() { console.log(`bar() ${this.data}`) } }
let myModule2 = { data: 'atguigu.com2222', foo() { console.log(`foo() ${this.data}`) }, bar() { console.log(`bar() ${this.data}`) } }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>02_namespace模式</title> </head> <body> <script type="text/javascript" src="module1.js"></script> <script type="text/javascript" src="module2.js"></script> <script type="text/javascript"> myModule1.foo() // foo() atguigu.com myModule1.bar() // bar() atguigu.com myModule2.foo() // foo() atguigu.com2222 myModule2.bar() // bar() atguigu.com2222 myModule1.data = 'other data' //能直接修改模塊內部的數據 myModule1.foo() // foo() other data </script> </body> </html>
IIFE模式: 匿名函數自調用(閉包)
IIFE : immediately-invoked function expression(當即調用函數表達式)
做用: 數據是私有的, 外部只能經過暴露的方法操做
問題: 若是當前這個模塊依賴另外一個模塊怎麼辦編程
(function (window) { let data = 'atguigu.com' // 數據 //操做數據的函數 function foo() { //用於暴露有函數 console.log(`foo() ${data}`) } function bar() {//用於暴露有函數 console.log(`bar() ${data}`) otherFun() //內部調用 } function otherFun() { //內部私有的函數 console.log('otherFun()') } //暴露行爲 window.myModule = {foo, bar} })(window)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>03_IIFE模式</title> </head> <body> <script type="text/javascript" src="module3.js"></script> <script type="text/javascript"> myModule.foo() // foo() atguigu.com myModule.bar() // bar() atguigu.com //myModule.otherFun() //myModule.otherFun is not a function console.log(myModule.data) //undefined 不能訪問模塊內部數據 myModule.data = 'xxxx' //不能修改的模塊內部的data,這只是給myModule對象增長了一個data屬性 myModule.foo() // 沒有改變,foo() atguigu.com </script> </body> </html>
IIFE模式加強 : 引入依賴安全
這就是現代模塊實現的基石
(function (window, $) { let data = 'atguigu.com' // 數據 // 操做數據的函數 function foo() { // 用於暴露有函數 console.log(`foo() ${data}`) $('body').css('background', 'red') } function bar() { // 用於暴露有函數 console.log(`bar() ${data}`) otherFun() // 內部調用 } function otherFun() { //內部私有的函數 console.log('otherFun()') } //暴露行爲 window.myModule = {foo, bar} })(window, jQuery)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>04_IIFE模式加強</title> </head> <body> <!--引入的js必須有必定順序--> <script type="text/javascript" src="jquery-1.10.1.js"></script> <script type="text/javascript" src="module4.js"></script> <script type="text/javascript"> myModule.foo() // foo() atguigu.com </script> </body> </html>
爲何要模塊化開發
首先來講明一下,項目中js爲何要模塊化的開發,當項目開發愈來愈複雜的時候,會常常遇到代碼衝突,每一個js文件之間的依賴關係,當js文件愈來愈多的時候頁面加載性能等等一些問題
代碼衝突:好比在團隊協做的過程當中,同事A寫了一個組件庫common的一個js文件,裏面有個操做選項卡的一個函數叫作tab,而後同事B在同一個頁面中進行修改的時候,也定義了一個叫作tab的函數,那這個時候,這兩個方法就衝突了(不只函數衝突,包括變量等等),通常狀況下,簡單的解決方案就是給這些函數或者變量加上命名空間(這個解決方案的缺點是名字比較長 , 只能下降衝突,不能徹底避免)
var above = {}; //名字比較長 , 只能下降衝突,不能徹底避免 above.a = 10; above.tab = function(){}; above.drag = function(){}; above.dialog = function(){}; //調用的時候須要加上前綴,若是命名空間比較長的時候,調用的時候更加麻煩 above.tab();
多個js文件之間的依賴關係:當項目愈來愈大的時候,項目須要將js進行分層,當a.js和b.js兩個文件都須要引入頁面中,而且b.js須要依賴a.js的時候,當時後期項目需求更改須要加入一個功能,在寫一個c.js文件,須要依賴a.js,當愈來愈多文件,文件之間有相互依賴的關係,若是少了某個依賴的文件那麼頁面就出錯了
模塊化的好處和問題
避免命名衝突(減小命名空間污染),更好的分離, 按需加載,更高複用性,高可維護性
模塊化能帶來不少好處,但現實開發中也會帶來問題
頁面引入加載script,產生的問題:請求過多,依賴模糊,難以維護,因此咱們須要一些模塊化的規範來解決這些問題
SeaJs簡介
Seajs庫的做用就是爲了解決代碼衝突,js模塊的依賴關係等等問題
Seajs,一個Web模塊加載框架,追求簡單、天然的代碼書寫和組織方式,:Sea.js 遵循 CMD 規範,模塊化JS代碼。依賴的自動加載、配置的簡潔清晰,可讓程序員更多地專一編碼。
Seajs優缺點
優勢:提升可維護性、模塊化編程、動態加載,前端性能優化
SeaJs與JQuery的區別
什麼是CMD 和AMD