前言
作为一名前端工程师,每天的清晨,你走进公司的大门,回味着前台妹子的笑容,摘下耳机,泡上一杯茶,打开 Terminal
进入对应的项目目录下,然后 npm run start / dev
或者 yarn start / dev
就开始了一天的工作。
当你需要进行时间的转换只需要使用 dayjs
或者 momentjs
, 当你需要封装 http 请求的时候,你可以用 fetch
或者 axios
, 当你需要做数据处理的时候,你可能会用 lodash
或者 underscore
。
这里还是要推荐下小编的web前端学习 群 : 569146385,不管你是小白还是大牛,小编我都欢迎,不定期分享干货,包括 小编自己整理的一份最新的web前端资料和0基础入门教程,欢迎初学和进 阶中的小伙伴。在不忙的时间我会给大家解惑。
不知道你有没有意识到,对于今天的我们而言,这些工具包让开发效率得到了巨大的提升,但是这一切是从什么开始的呢?
这些就要从 Modular design (模块化设计)
说起:
Modular design (模块化设计)
在我刚接触前端的时候,经常听说 Modular design (模块化设计)
这样的术语,面试时也会经常被问到,“聊聊前端的模块化”这样的问题,或许很多人都可以说出几个熟悉的名词,甚至是他们之间的区别:
- IIFE [Immediately Invoked Function Expression]
- Common.js
- AMD
- CMD
- ES6 Module
但就像你阅读一个项目的源码一样,如果从第一个 commit
开始研究,那么你能收获的或许不仅仅是,知道他们有什么区别,更重要的是,能够知道在此之前的历史中,是什么样的原因,导致了区别于旧的规范而产生的新规范,并且基于这些,或许你能够从中体会到这些改变意味着什么,甚至在将来的某个时刻,你也能成为这规则的制定者之一。
所以让我们回到十年前,来看看是怎么实现模块化设计的:
IIFE
IIFE 是 Immediately Invoked Function Expression 的缩写,作为一个基础知识,很多人可能都已经知道 IIFE 是怎么回事,(如果你已经掌握了 IIFE,可以跳过这节阅读后面的内容) 但这里我们仍旧会解释一下,它是怎么来的,因为在后面我们还会再次提到它:
最开始,我们对于模块区分的概念,可能是从文件的区分开始的,在一个简易的项目中,编程的习惯是通过一个 HTML 文件加上若干个 JavaScript 文件来区分不同的模块,就像这样:
我们可以通过这样一个简单的项目来说明,来看看每个文件里面的内容:
demo.html
这个文件,只是简单的引入了其他的几个 JavaScript 文件:
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>demo</title>
</head>
<script src="main.js"></script>
<script src="header.js"></script>
<script src="footer.js"></script>
<body></body>
</html>
复制代码
其他三个 JavaScript 文件
在不同的 js 文件中我们定义了不同的变量,分别对应文件名:
var header = '这是一条顶部信息' //header.js
var main_message = '这是一条内容信息' //main.js
var main_error = '这是一条错误信息' //main.js
var footer = '这是一条底部信息' //footer.js
复制代码
像这样通过不同的文件来声明变量的方式,实际上无法将这些变量区分开来。
它们都绑定在全局的 window / Global(node 环境下的全局变量) 对象上,尝试去打印验证一下:
这简直就是一场噩梦,你可能没有意识到这会导致什么严重的结果,我们试着在 footer.js 中对 header
变量进行赋值操作,让我们在末尾加上这样一行代码:
header = 'nothing'
复制代码
打印后你就会发现,window.header
的已经被更改了:
试想一下,你永远无法预料在什么时候什么地点无意中就改掉了之前定义的某个变量,如果这是在一个团队中,这是一件多么可怕的事情。
Okay,现在我们知道,仅仅通过不同的文件,我们无法做到将这些变量分开,因为它们都被绑在了同一个 window 变量上。
但是更重要的是,怎么去解决呢?我们都知道,在 JavaScript 中,函数拥有自己的作用域 的,也就是说,如果我们可以用一个函数将这些变量包裹起来,那这些变量就不会直接被声明在全局变量 window 上了:
所以现在 main.js 的内容会被修改成这样:
function mainWarraper() {
var main_message = '这是一条内容信息' //main.js
var main_error = '这是一条错误信息' //main.js
console.log('error:', main_error)
}
mainWarraper()
复制代码
为了确保我们定义在函数 mainWarraper 的内容会被执行,所以我们必须在这里执行 mainWarraper() 本身,现在我们在 window 里面找不到 main_message
和 main_error
了,因为它们被隐藏在了 mainWarraper
中,但是 mainWarraper
仍旧污染了我们的 window:
这个方案还不够完美,怎么改进呢?
答案就是我们要说的 IIFE 我们可以定义一个 立即执行的匿名函数 来解决这个问题:
(function() {
var main_message = '这是一条内容信息' //main.js
var main_error = '这是一条错误信息' //main.js
console.log('error:', main_error)
})()
复制代码