Hi Da Gei Ho~ 我是 Winnie , 今天来到了第三天
前情提要:
在昨天的文章中,我们简单的解释了下 模组 与 模组化 是什麽之後,今天我们将继续 简单了解 JS模组化规范 的 演进过程。
不知道大家记不记得,在上篇的文章我们有说到 早期的JavaScript 是还没有模组化的概念的,所以在当时 只能以function 档案来区分并透过<script><script/>
的方式来载入,就像以下程序码:
//Monday.js
function Monday(month, day){
return month+"/"+day
}
//Tuesday.js
function Tuesday(month, day){
return month+"/"+day
}
//Wednesday.js
function Wednesday(month, day){
return month+"/"+day
}
<html lang="en">
<body>
<script type="text/javascript" src="../lib/juqery.js"></script>
<script type="text/javascript" src="../js/Monday.js"></script>
<script type="text/javascript" src="../js/Tuesday.js"></script>
<script type="text/javascript" src="../js/Wednesday.js"></script>
</body>
</html>
**依照上面程序码载入的方式,如果使用不小心很容易就会导致以下缺点:
//a.js
var Wednesday = '9/15'
.... 略
//b.js
var Wednesday = '9/16'
....略
console.log(Wednesday)
从上程序码来看,原本应该 星期三应该是9/15,但因为其他命名相同的冲突而被覆盖 输出 9/16
引入的档案相互依赖性高,顺序很重要
如:Wednesday.js
依赖了Tuesday.js
那麽载入时就必须先使用Tuesday.js
再使用Wednesday.js
,一但顺序相反,就很容易出错
後来为解决 命名冲突及污染全域的问题 ,进而发展出 IIFE(立即执行函式) 模拟模组的方式,而IIFE的就如同他名字一样,当下被宣告function就会立即执行。
其中在模拟模组化的过程中,还 使用到了 JavaScript的特性 闭包Closures 让区域变数和方法锁在内部,将需要给外部使用的变数传出去,而这样的好处就是区域性的变数 就不会污染到全域性作用域。
(function(){
var name = 'winnie;
var sayHello = function (){
console.log('hello ! I'm'+ name);
}
sayHello(); // hello! I'm winnie
})()
虽然以上 实现了简单的程序码模组化,同时也解决了污染作用域的问题,但针对 管理 相互依赖的问题还是依然存在。
所以随着技术的进步(老话一句),为了能让人们更方便,所以後期在 Node.js 中大家也开始发展出许多方便的第三模组库供人使用,因此针对模组化也有了不同的规范版本,其中 像是 我们常听到的 CommonJS、 AMD 、 CMD 还有 近期的ES6 module
而在这麽多规范中,想必大家应该常常会看到 require/module.exports
与 import/exports
的用法吧?
是的!接着我们就要来介绍这两个的规范,分别是 common.js & ES6 module (抱歉!其实 AMD、CMD也常见,後续有机会会再补上 )
如果大家有印象,在 Common JS标准最主要的规范就是输出模组时用 module.exports
,引入时用 require
。
范例如下:
// banana.js
//一个一个 汇出
exports.banana = 'I m banana'
module.exports.banana = function(){}
//整体汇出
module.exports = { banana: 'I m banana', banana:function(){}}
const banana = require('./banana.js')
console.log(banana.banana) // 'I m banana'
而这个用法在当时也被Node.js采用 ,所以现今我们时常会在各种程序码中 看到这个形式来做模组的输出与引用。
但很可惜的是,虽然Common.js被Node.js采用成模组化的规范,但很可惜的是,在浏览器上面依然没办法使用 ,简单来说 就是 浏览器 只看得懂 JavaScript 啊,而这也是我们 现今为何要使用 打包工具 的最主要原因。
对!终於提到 打包工具,现在你终於能稍微知道为什麽要用Webpack了啊!
画重点!!就是在当时 浏览器的原生并不支援 CommonJS),必须透过打包工具的编译 才能在浏览器上面使用。
而 ES6 出来之後,模组化 有了正式的规范,也就是近期很常看到的 import 与 export的形式
范例如下:
// hello.js
// 多个输出名称
export function sayHello(){
console.log('Hello');
}
export function sayBye(){
console.log('Bye');
}
// 单一输出 (这边需注意的是 一只档案中只能有一个 export default)
function sayGoodnight(){
console.log(‘Goodnight’)
}
export default sayGoodnight
---------------------------------
// other.js
// 引入hello模组的sayHello方法
import { sayHello, sayBye } from './hello';
sayHello(); // => Hello
sayBye(); // => Bye
这就是 ES6 Module 。
到这边,你可能会想既然原生都支持了,为何还要打包工具?
但事情是这样的,人生有十之八九不会照着我们想走的走。
所以在 ES6 Module 这边也是一样,虽然是浏览器原生支持的,但还是有在某些浏览器不支援的问题,就像下面这张图一样
而同时如果在 Node.js 上面试图执行 import 这个语法,也还出现一个 SyntaxError: Unexpected identifier 的错误,因为 Node.js 不认识 import。但总不可能因为不支援就要抛弃他人写好的给力模组吧。
综合以上这些可能会碰到的问题,如果想要人生顺利,我们还是需要透过 打包工具 来帮我们处理掉这些问题。
最後,这篇文章简单的针对 JS中 模组化从有到无的出现过程及常见模组化规范(其实还少讲了很多XD,像是AMD、CMD)进行了描述,虽然可能不是说得很详细,但这篇文章的最主要目的还是想透过 模组化的微历史 来了解 为何使用打包工具来编译的目的。
如果文章有错误的地方,再麻烦不吝啬的给予指教 谢谢 !!
昨天我们已经将注册帐号、帐号登入实作完成了,今天我们要来把剩下的帐号登出以及密码重设功能来实作完成 ...
如同许多的程序语言,SQL 本身也有内建函数,像是前些天的篇幅内曾用的 COUNT, SUM, AV...
不怎麽重要的前言 上一篇介绍了两个小题目,稍微带过解题的思路,以及多重回圈(巢状回圈)的概念。 现在...
Q: 剩下 5 篇来点实用也不实用的范例吧~~ A: 毕竟效果还是要看设计的美感,这是很看天份的(...
这是我一边学习一边写下的笔记,如果内容有错,恳请在下方留言跟我说,我会非常感谢的!!! 变数 「变数...