生活随笔
收集整理的這篇文章主要介紹了
【重要】ES6-23 JavaScript模块化
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
- 前端js模塊化的演變發展
- 模塊化解決的問題
- 傳統模塊化、插件化
- CommonJS
- AMD/CMD
- ES6模塊化
ES6以前 沒有js引擎
一開始js寫在html的script標簽里js內容增多,抽取出index.js文件,外部引入js再增加,index.html對應index.js index2.html對應index2.js(模塊化概念的誕生)含有可復用的代碼,提出公共的common.js引入common.js的所有內容不合理 → 不能光以頁面為基準來區分程序塊、分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時阻塞,所以這4個js文件必須按內部的邏輯,順序加載,順序是不能變的
- 這4個文件共用了JS作用域-全局作用域
- 因此:污染全局 + if 變量重名 → 變量覆蓋
模塊化解決問題:
加載順序污染全局
案例二 IIFE注入
歷史問題:ECMA規定語句應當以分號結尾,早前js都是運行在瀏覽器上的,但瀏覽器支持判斷當前是否是語句,是就自動加上分號。當使用多個IIFE,且不寫分號時,瀏覽器無法識別,報錯。因此約定俗成的規定,IIFE前面必須寫分號,更規范的是結尾也寫分號,即
;(function(){
})();
使用IIFE,解決污染全局,為了易于拓展,模塊應當返回對象新的問題,若沒有拋到全局,如何在模塊之間獲得相應的abc用變量接收IIFE的返回值,在需要用的的模塊傳入(注入),解決了模塊依賴注意:模塊名完全獨立,不應該重復,因此在全局聲明了,而內部abc屬于數據類型的變量,不能在全局聲明注意:不注入moduleABC,直接用moduleA.a訪問變量能得到正確結果,但注入意味著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
);
存在問題
順序問題依然未解決
插件
構造函數執行init構造函數掛載到window(插件)script里實例化
案例三 CommonJS
NodeJS誕生帶來了前所未有的模塊化體驗
require(...) 引入模塊
module.exports導出模塊
運行在node環境下
CommonJS是模塊化規范,來源于NodeJS
在服務端開發,引入模塊用require,是同步的方法
只要引用,就會創建模塊的實例
有非常強的緩存機制
一定是在Node上運行,客戶端運行不了(要借助webpack?)
require實質是IIFE,會傳入一些參數
(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就能運行在客戶端
- 所有依賴加載完成后才會執行回調函數(前置依賴)
AMD Asynchronous Module Definition 異步模塊定義
來源于CommonJS
define(moduleName, [module], factory) 定義模塊
require([module], callback) 引入模塊
RequireJS實現AMD
引入require.js定義+使用依賴時注入使用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
- 阿里對模塊化的貢獻
- require加載 define定義
- exports導出(return和它的效果一直) module操作
- 需要配置模塊URL
- 依賴加載完畢后執行factory
- 依賴就近 按需加載(這是和CommonJS AMD本質上的不同)
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模塊化規范
import module from ‘模塊路徑’ 導入模塊
export module 導出模塊
Uncaught SyntaxError: Cannot use import statement outside a module
調試過程中的報錯解答
<!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的區別
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輸出的是一個值的拷貝es6模塊輸出的是值的引用commonjs模塊是在運行時加載(commonjs運行在服務端,require時加載)es6模塊是在編譯時加載
YUI
總結
以上是生活随笔為你收集整理的【重要】ES6-23 JavaScript模块化的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。