├── 3. AMD和CMD ├── 3-1. 浏览器端模块化的难题 │ ├── b.js │ ├── a.js │ ├── index.js │ ├── index.html │ ├── 笔记.md │ └── 笔记.html ├── 3-3. CMD │ ├── js │ │ ├── a.js │ │ ├── b.js │ │ ├── index.js │ │ └── sea.js │ ├── 笔记.md │ └── index.html └── 3-2. AMD │ ├── 笔记.md │ ├── js │ ├── a.js │ ├── index.js │ └── b.js │ └── index.html ├── 4. ES6模块化 ├── 4-2. 基本导入导出 │ ├── module │ │ ├── init.js │ │ ├── b.js │ │ ├── index.js │ │ └── a.js │ ├── assets │ │ └── 2019-12-03-17-00-44.png │ ├── index.html │ ├── 笔记.md │ └── 笔记.html ├── 4-5. ES6模块化练习 │ ├── module │ │ ├── index.js │ │ ├── game.js │ │ ├── map.js │ │ ├── ui.js │ │ └── play.js │ ├── imgs │ │ ├── box.png │ │ ├── player.png │ │ ├── wall.jpg │ │ └── over_box.png │ └── index.html ├── 4-4. ES6模块化的其他细节 │ ├── module │ │ ├── a.js │ │ ├── arrayPatcher.js │ │ ├── m1.js │ │ ├── m2.js │ │ ├── m.js │ │ └── index.js │ ├── assets │ │ └── 2019-12-04-14-33-14.png │ ├── index.html │ ├── 笔记.md │ └── 笔记.html ├── 4-3. 默认导入导出 │ ├── module │ │ ├── a.js │ │ └── index.js │ ├── assets │ │ └── 2019-12-03-17-00-44.png │ ├── index.html │ ├── 笔记.md │ └── 笔记.html └── 4-1. ES6模块化简介 │ └── 笔记.md ├── 2. CommonJS ├── 2-2. CommonJS │ ├── b.js │ ├── util.js │ ├── assets │ │ ├── 2019-12-02-11-15-01.png │ │ └── 2019-12-02-11-27-12.png │ ├── index.js │ ├── 笔记.md │ └── 笔记.html ├── 2-1. 安装nodejs │ ├── index.js │ ├── assets │ │ ├── 2019-12-02-10-57-23.png │ │ └── 2019-12-02-10-59-43.png │ └── 笔记.md └── 2-3. CommonJS练习 │ ├── test.js │ ├── 练习题.md │ ├── util.js │ ├── index.js │ └── poker.js └── 1. 概述 └── 1-1. JS模块化发展史 ├── assets └── 2019-11-28-15-45-47.png ├── 笔记.md └── 笔记.html /3. AMD和CMD/3-1. 浏览器端模块化的难题/b.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /3. AMD和CMD/3-1. 浏览器端模块化的难题/a.js: -------------------------------------------------------------------------------- 1 | require("./b.js") -------------------------------------------------------------------------------- /4. ES6模块化/4-2. 基本导入导出/module/init.js: -------------------------------------------------------------------------------- 1 | console.log("初始化代码") -------------------------------------------------------------------------------- /4. ES6模块化/4-5. ES6模块化练习/module/index.js: -------------------------------------------------------------------------------- 1 | import "./game.js" -------------------------------------------------------------------------------- /4. ES6模块化/4-2. 基本导入导出/module/b.js: -------------------------------------------------------------------------------- 1 | console.log("b模块运行了") 2 | 3 | export var b = 123; -------------------------------------------------------------------------------- /3. AMD和CMD/3-1. 浏览器端模块化的难题/index.js: -------------------------------------------------------------------------------- 1 | //一大堆代码 2 | require("./a.js") //同步代码,必须等待 3 | //一大堆代码 -------------------------------------------------------------------------------- /2. CommonJS/2-2. CommonJS/b.js: -------------------------------------------------------------------------------- 1 | console.log("b模块执行了!") 2 | 3 | var u = require("./util"); 4 | 5 | console.log(u.abc); -------------------------------------------------------------------------------- /4. ES6模块化/4-4. ES6模块化的其他细节/module/a.js: -------------------------------------------------------------------------------- 1 | export var name = "模块a"; 2 | 3 | export default function () { 4 | name = "module a"; 5 | } -------------------------------------------------------------------------------- /4. ES6模块化/4-5. ES6模块化练习/imgs/box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuYi-Edu/DuYi-Modularity/HEAD/4. ES6模块化/4-5. ES6模块化练习/imgs/box.png -------------------------------------------------------------------------------- /4. ES6模块化/4-4. ES6模块化的其他细节/module/arrayPatcher.js: -------------------------------------------------------------------------------- 1 | Array.prototype.print = function () { 2 | console.log(this); 3 | } 4 | 5 | //一些其他的代码 -------------------------------------------------------------------------------- /4. ES6模块化/4-5. ES6模块化练习/imgs/player.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuYi-Edu/DuYi-Modularity/HEAD/4. ES6模块化/4-5. ES6模块化练习/imgs/player.png -------------------------------------------------------------------------------- /4. ES6模块化/4-5. ES6模块化练习/imgs/wall.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuYi-Edu/DuYi-Modularity/HEAD/4. ES6模块化/4-5. ES6模块化练习/imgs/wall.jpg -------------------------------------------------------------------------------- /2. CommonJS/2-1. 安装nodejs/index.js: -------------------------------------------------------------------------------- 1 | console.log("Hello NodeJs");//是不是ES标准 2 | setInterval(function(){ 3 | console.log("Hello") 4 | }, 1000) -------------------------------------------------------------------------------- /4. ES6模块化/4-5. ES6模块化练习/imgs/over_box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuYi-Edu/DuYi-Modularity/HEAD/4. ES6模块化/4-5. ES6模块化练习/imgs/over_box.png -------------------------------------------------------------------------------- /2. CommonJS/2-2. CommonJS/util.js: -------------------------------------------------------------------------------- 1 | var count = 0; //需要隐藏的内部实现 2 | 3 | console.log("util模块执行了!") 4 | 5 | module.exports = { 6 | abc: 123 7 | } -------------------------------------------------------------------------------- /4. ES6模块化/4-3. 默认导入导出/module/a.js: -------------------------------------------------------------------------------- 1 | export var a = 1; 2 | export var b = 2; 3 | 4 | export default { 5 | fn: function () { }, 6 | name: "adsfaf" 7 | } -------------------------------------------------------------------------------- /1. 概述/1-1. JS模块化发展史/assets/2019-11-28-15-45-47.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuYi-Edu/DuYi-Modularity/HEAD/1. 概述/1-1. JS模块化发展史/assets/2019-11-28-15-45-47.png -------------------------------------------------------------------------------- /4. ES6模块化/4-2. 基本导入导出/assets/2019-12-03-17-00-44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuYi-Edu/DuYi-Modularity/HEAD/4. ES6模块化/4-2. 基本导入导出/assets/2019-12-03-17-00-44.png -------------------------------------------------------------------------------- /4. ES6模块化/4-3. 默认导入导出/assets/2019-12-03-17-00-44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuYi-Edu/DuYi-Modularity/HEAD/4. ES6模块化/4-3. 默认导入导出/assets/2019-12-03-17-00-44.png -------------------------------------------------------------------------------- /2. CommonJS/2-1. 安装nodejs/assets/2019-12-02-10-57-23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuYi-Edu/DuYi-Modularity/HEAD/2. CommonJS/2-1. 安装nodejs/assets/2019-12-02-10-57-23.png -------------------------------------------------------------------------------- /2. CommonJS/2-1. 安装nodejs/assets/2019-12-02-10-59-43.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuYi-Edu/DuYi-Modularity/HEAD/2. CommonJS/2-1. 安装nodejs/assets/2019-12-02-10-59-43.png -------------------------------------------------------------------------------- /2. CommonJS/2-2. CommonJS/assets/2019-12-02-11-15-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuYi-Edu/DuYi-Modularity/HEAD/2. CommonJS/2-2. CommonJS/assets/2019-12-02-11-15-01.png -------------------------------------------------------------------------------- /2. CommonJS/2-2. CommonJS/assets/2019-12-02-11-27-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuYi-Edu/DuYi-Modularity/HEAD/2. CommonJS/2-2. CommonJS/assets/2019-12-02-11-27-12.png -------------------------------------------------------------------------------- /3. AMD和CMD/3-3. CMD/js/a.js: -------------------------------------------------------------------------------- 1 | define(function (require, exports, module) { 2 | var b = require("b") 3 | console.log("a模块的内部代码", b) 4 | module.exports = "a模块的内容" 5 | }) -------------------------------------------------------------------------------- /4. ES6模块化/4-3. 默认导入导出/module/index.js: -------------------------------------------------------------------------------- 1 | // import data from "./a.js" //将a.js模块中的默认导出放置到常量data中 2 | import data, { a, b } from "./a.js" 3 | 4 | console.log(data, a, b) 5 | 6 | -------------------------------------------------------------------------------- /4. ES6模块化/4-4. ES6模块化的其他细节/assets/2019-12-04-14-33-14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuYi-Edu/DuYi-Modularity/HEAD/4. ES6模块化/4-4. ES6模块化的其他细节/assets/2019-12-04-14-33-14.png -------------------------------------------------------------------------------- /3. AMD和CMD/3-3. CMD/js/b.js: -------------------------------------------------------------------------------- 1 | define(function (require, exports, module) { 2 | //模块内部的代码 3 | console.log("b模块的内部代码") 4 | module.exports = { 5 | name: "b模块", 6 | data: "b模块的数据" 7 | } 8 | }) -------------------------------------------------------------------------------- /3. AMD和CMD/3-3. CMD/js/index.js: -------------------------------------------------------------------------------- 1 | define((require, exports, module) => { 2 | require.async("a", function(a){ 3 | console.log(a) 4 | }) 5 | require.async("b", function(b){ 6 | console.log(b) 7 | }) 8 | }) -------------------------------------------------------------------------------- /4. ES6模块化/4-2. 基本导入导出/module/index.js: -------------------------------------------------------------------------------- 1 | import "./b.js"; 2 | import "./init.js" 3 | import * as a from "./a.js" 4 | 5 | // var b = 3; 6 | // console.log(b2) 7 | // console.log(name, age); 8 | // console.log(b) 9 | 10 | console.log(a.a, a.age, a.name) -------------------------------------------------------------------------------- /3. AMD和CMD/3-3. CMD/笔记.md: -------------------------------------------------------------------------------- 1 | # CMD 2 | 3 | 全称是Common Module Definition,公共模块定义规范 4 | 5 | sea.js实现了CMD规范 6 | 7 | 在CMD中,导入和导出模块的代码,都必须放置在define函数中 8 | 9 | ```js 10 | 11 | define(function(require, exports, module){ 12 | //模块内部的代码 13 | }) 14 | 15 | ``` -------------------------------------------------------------------------------- /4. ES6模块化/4-4. ES6模块化的其他细节/module/m1.js: -------------------------------------------------------------------------------- 1 | export const a = "m1-a"; 2 | export const b = "m1-b"; 3 | export const c = "m1-c"; 4 | 5 | export default "m1-default"; 6 | 7 | /* 8 | { 9 | a:xx, 10 | b:xx, 11 | c:xx, 12 | default:xxx 13 | } 14 | */ -------------------------------------------------------------------------------- /4. ES6模块化/4-4. ES6模块化的其他细节/module/m2.js: -------------------------------------------------------------------------------- 1 | export const a = "m2-a"; 2 | export const k = "m2-k"; 3 | export const t = "m2-t"; 4 | 5 | export default "m2-default"; 6 | 7 | /* 8 | { 9 | a:xx, 10 | k:xx, 11 | t:xx, 12 | default:xxx 13 | } 14 | */ -------------------------------------------------------------------------------- /2. CommonJS/2-2. CommonJS/index.js: -------------------------------------------------------------------------------- 1 | 2 | //nodejs中导入模块,使用相对路径,并且必须以./或../开头 3 | var util1 = require("./util.js") 4 | var util2 = require("./util.js") 5 | console.log(util1 === util2); 6 | require("./b") 7 | require("./b") 8 | require("./b") 9 | require("./b") 10 | -------------------------------------------------------------------------------- /4. ES6模块化/4-4. ES6模块化的其他细节/module/m.js: -------------------------------------------------------------------------------- 1 | // import { a, b } from "./m1.js"; 2 | // import m2, { k } from "./m2.js" 3 | 4 | // export { a, b, k, m2 as default } 5 | 6 | export { a, b } from "./m1.js" 7 | export { k, default, a as m2a } from "./m2.js" 8 | export const r = "m-r" -------------------------------------------------------------------------------- /3. AMD和CMD/3-2. AMD/笔记.md: -------------------------------------------------------------------------------- 1 | # AMD 2 | 3 | 全称是Asynchronous Module Definition,即异步模块加载机制 4 | 5 | require.js实现了AMD规范 6 | 7 | 在AMD中,导入和导出模块的代码,都必须放置在define函数中 8 | 9 | ```js 10 | 11 | define([依赖的模块列表], function(模块名称列表){ 12 | //模块内部的代码 13 | return 导出的内容 14 | }) 15 | 16 | ``` -------------------------------------------------------------------------------- /2. CommonJS/2-3. CommonJS练习/test.js: -------------------------------------------------------------------------------- 1 | // var util = require("./util") 2 | 3 | // var arr = [6,4,3,2,6,8,8,32,5]; 4 | 5 | // util.sortRandom(arr); 6 | 7 | // console.log(arr); 8 | 9 | var Poker = require("./poker") 10 | 11 | var p = new Poker(4, 11); 12 | console.log(p.toString()); -------------------------------------------------------------------------------- /3. AMD和CMD/3-2. AMD/js/a.js: -------------------------------------------------------------------------------- 1 | // define(["b"], function(b){ 2 | // console.log("a模块的内部代码") 3 | // return "a模块的内容"; 4 | // }) 5 | 6 | define(function (require, exports, module) { 7 | var b = require("b") 8 | console.log("a模块的内部代码", b) 9 | module.exports = "a模块的内容" 10 | }) -------------------------------------------------------------------------------- /3. AMD和CMD/3-2. AMD/js/index.js: -------------------------------------------------------------------------------- 1 | // define(["b", "a"], function (b, a) { 2 | // //等b.js加载完成后运行该函数 3 | // //模块内部的代码 4 | // console.log(b, a) 5 | // }) 6 | 7 | define((require, exports, module) => { 8 | var a = require("a"), 9 | b = require("b"); 10 | console.log(b, a) 11 | }) -------------------------------------------------------------------------------- /2. CommonJS/2-3. CommonJS练习/练习题.md: -------------------------------------------------------------------------------- 1 | 制作一个斗地主洗牌发牌的程序 2 | 3 | 划分模块: 4 | 5 | 1. 工具模块,导出一个函数,用于将一个数组中的所有内容乱序排列 6 | 2. 扑克牌构造函数(类) 7 | 1. 属性 8 | 1. 花色(1~4,♣、♥、♦、♠) 9 | 2. 牌面(1~15,14小王,15大王) 10 | 2. 方法 11 | 1. toString:得到该扑克牌的字符串 12 | 3. 入口模块(入口文件) 13 | 1. 创建54张扑克牌 14 | 2. 洗牌 15 | 3. 发牌 -------------------------------------------------------------------------------- /4. ES6模块化/4-4. ES6模块化的其他细节/module/index.js: -------------------------------------------------------------------------------- 1 | // // import method, { name } from "./a.js" 2 | 3 | // // console.log(name) 4 | // // method(); 5 | // // console.log(name) 6 | 7 | // import "./arrayPatcher.js" 8 | 9 | // var arr = [3,4,6,6,7]; 10 | // arr.print(); 11 | 12 | import * as m from "./m.js" 13 | 14 | console.log(m) -------------------------------------------------------------------------------- /4. ES6模块化/4-1. ES6模块化简介/笔记.md: -------------------------------------------------------------------------------- 1 | # ES6模块化简介 2 | 3 | ECMA组织参考了众多社区模块化标准,终于在2015年,随着ES6发布了官方的模块化标准,后成为ES6模块化 4 | 5 | ES6模块化具有以下的特点 6 | 7 | 1. 使用依赖**预声明**的方式导入模块 8 | 1. 依赖延迟声明 9 | 1. 优点:某些时候可以提高效率 10 | 2. 缺点:无法在一开始确定模块依赖关系(比较模糊) 11 | 2. 依赖预声明 12 | 1. 优点:在一开始可以确定模块依赖关系 13 | 2. 缺点:某些时候效率较低 14 | 2. 灵活的多种导入导出方式 15 | 3. 规范的路径表示法:所有路径必须以./或../开头 -------------------------------------------------------------------------------- /3. AMD和CMD/3-1. 浏览器端模块化的难题/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /4. ES6模块化/4-2. 基本导入导出/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /4. ES6模块化/4-3. 默认导入导出/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /4. ES6模块化/4-4. ES6模块化的其他细节/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /3. AMD和CMD/3-2. AMD/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /4. ES6模块化/4-2. 基本导入导出/module/a.js: -------------------------------------------------------------------------------- 1 | import "./b.js" //这条导入语句,仅会运行模块,不适用它内部的任何导出 2 | 3 | export var a = 1; //导出a,值为1,类似于CommonJS中的exports.a = 1 4 | export function test() { //导出test,值为一个函数,类似于CommonJS中的exports.test = function (){} 5 | 6 | } 7 | 8 | export class Person { 9 | 10 | } 11 | 12 | export const name = "abc" 13 | 14 | var age = 18; 15 | var sex = 1; 16 | 17 | export { age, sex } //将age变量的名称作为导出的名称,age变量的值,作为导出的值 18 | -------------------------------------------------------------------------------- /3. AMD和CMD/3-2. AMD/js/b.js: -------------------------------------------------------------------------------- 1 | // define(function () { 2 | // //模块内部的代码 3 | // console.log("b模块的内部代码") 4 | // var a = 1; 5 | // var b = 234; 6 | // return { 7 | // name: "b模块", 8 | // data: "b模块的数据" 9 | // } 10 | // }) 11 | 12 | define(function (require, exports, module) { 13 | //模块内部的代码 14 | console.log("b模块的内部代码") 15 | module.exports = { 16 | name: "b模块", 17 | data: "b模块的数据" 18 | } 19 | }) -------------------------------------------------------------------------------- /3. AMD和CMD/3-3. CMD/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Document 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /4. ES6模块化/4-4. ES6模块化的其他细节/笔记.md: -------------------------------------------------------------------------------- 1 | # ES6模块化的其他细节 2 | 3 | 1. **尽量导出不可变值** 4 | 5 | 当导出一个内容时,尽量保证该内容是不可变的(大部分情况都是如此) 6 | 7 | 因为,虽然导入后,无法更改导入内容,但是在导入的模块内部却有可能发生更改,这将导致一些无法预料的事情发生 8 | 9 | 2. **可以使用无绑定的导入用于执行一些初始化代码** 10 | 11 | 如果我们只是想执行模块中的一些代码,而不需要导入它的任何内容,可以使用无绑定的导入: 12 | 13 | ```js 14 | import "模块路径" 15 | ``` 16 | 17 | 3. **可以使用绑定再导出,来重新导出来自另一个模块的内容** 18 | 19 | 有的时候,我们可能需要用一个模块封装多个模块,然后有选择的将多个模块的内容分别导出,可以使用下面的语法轻松完成 20 | 21 | ```js 22 | export {绑定的标识符} from "模块路径" 23 | ``` 24 | 25 | ![](assets/2019-12-04-14-33-14.png) -------------------------------------------------------------------------------- /2. CommonJS/2-1. 安装nodejs/笔记.md: -------------------------------------------------------------------------------- 1 | # 安装nodejs 2 | 3 | 官网地址:https://nodejs.org/zh-cn/ 4 | 5 | **浏览器** 6 | 7 | 浏览器运行的是html页面,并加载页面中通过script元素引入的js 8 | 9 | ![](assets/2019-12-02-10-57-23.png) 10 | 11 | **nodejs** 12 | 13 | nodejs直接运行某个js文件,该文件被称之为入口文件 14 | 15 | ![](assets/2019-12-02-10-59-43.png) 16 | 17 | nodejs遵循EcmaScript标准,但由于脱离了浏览器环境,因此: 18 | 19 | 1. 你可以在nodejs中使用EcmaScript标准的任何语法或api,例如:循环、判断、数组、对象等 20 | 2. 你不能在nodejs中使用浏览器的 web api,例如:dom对象、window对象、document对象等 21 | 22 | 由于大部分开发者是从浏览器端开发转向nodejs开发的,为了降低开发者的学习成本,nodejs中提供了一些和浏览器web api同样的对象或函数,例如:console、setTimeout、setInterval等 -------------------------------------------------------------------------------- /2. CommonJS/2-3. CommonJS练习/util.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | /** 3 | * 将一个数组的内容打乱 4 | * @param {*} arr 数组 5 | */ 6 | sortRandom: function (arr) { 7 | arr.sort(function (a, b) { 8 | return Math.random() - 0.5; 9 | }) 10 | }, 11 | /** 12 | * 打印一个扑克牌的数组 13 | * @param {*} pokers 14 | */ 15 | print: function (pokers) { 16 | var str = ""; 17 | for (var i = 0; i < pokers.length; i++) { 18 | var p = pokers[i]; 19 | str += p.toString() + " "; 20 | } 21 | console.log(str); 22 | } 23 | } -------------------------------------------------------------------------------- /2. CommonJS/2-3. CommonJS练习/index.js: -------------------------------------------------------------------------------- 1 | var pokers = []; //扑克牌的数组 2 | var Poker = require("./poker") //导入扑克牌的构造函数 3 | for (var i = 1; i <= 13; i++) {//循环牌面 4 | for (var j = 1; j <= 4; j++) {//循环花色 5 | pokers.push(new Poker(j, i)); 6 | } 7 | } 8 | pokers.push(new Poker(null, 14), new Poker(null, 15)); 9 | 10 | //打乱扑克牌 11 | var util = require("./util"); 12 | util.sortRandom(pokers); 13 | 14 | var player1 = pokers.slice(0, 17); 15 | var player2 = pokers.slice(17, 34); 16 | var player3 = pokers.slice(34, 51); 17 | var desk = pokers.slice(51) 18 | 19 | console.log("玩家1:") 20 | util.print(player1); 21 | 22 | console.log("玩家2:") 23 | util.print(player2); 24 | 25 | console.log("玩家3:") 26 | util.print(player3); 27 | 28 | console.log("桌面:") 29 | util.print(desk); -------------------------------------------------------------------------------- /4. ES6模块化/4-3. 默认导入导出/笔记.md: -------------------------------------------------------------------------------- 1 | # 默认导入导出 2 | 3 | ![](assets/2019-12-03-17-00-44.png) 4 | 5 | ## 默认导出 6 | 7 | 每个模块,除了允许有多个基本导出之外,还允许有一个默认导出 8 | 9 | 默认导出类似于CommonJS中的```module.exports```,由于只有一个,因此无需具名 10 | 11 | 具体的语法是 12 | 13 | ```js 14 | export default 默认导出的数据 15 | ``` 16 | 17 | 或 18 | 19 | ```js 20 | export {默认导出的数据 as default} 21 | ``` 22 | 23 | 由于每个模块仅允许有一个默认导出,因此,每个模块不能出现多个默认导出语句 24 | 25 | ## 默认导入 26 | 27 | 需要想要导入一个模块的默认导出,需要使用下面的语法 28 | 29 | ```js 30 | import 接收变量名 from "模块路径" 31 | ``` 32 | 33 | 类似于CommonJS中的 34 | ```js 35 | var 接收变量名 = require("模块路径") 36 | ``` 37 | 38 | 由于默认导入时变量名是自行定义的,因此没有别名一说 39 | 40 | 如果希望同时导入某个模块的默认导出和基本导出,可以使用下面的语法 41 | 42 | ```js 43 | import 接收默认导出的变量, {接收基本导出的变量} from "模块路径" 44 | ``` 45 | 46 | 注:如果使用*号,会将所有基本导出和默认导出聚合到一个对象中,默认导出会作为属性default存在 -------------------------------------------------------------------------------- /4. ES6模块化/4-5. ES6模块化练习/module/game.js: -------------------------------------------------------------------------------- 1 | import { playerMove, isWin } from "./play.js" 2 | import showUI from "./ui.js" 3 | 4 | showUI(); 5 | var over = false 6 | //完成整个游戏 7 | 8 | window.onkeydown = function (e) { 9 | if (over) { 10 | return; 11 | } 12 | var result = false; 13 | if (e.key === "ArrowUp") { 14 | result = playerMove("up"); 15 | } 16 | else if (e.key === "ArrowDown") { 17 | result = playerMove("down") 18 | } 19 | else if (e.key === "ArrowLeft") { 20 | result = playerMove("left") 21 | } 22 | else if (e.key === "ArrowRight") { 23 | result = playerMove("right") 24 | } 25 | 26 | if (result) { 27 | showUI(); 28 | if (isWin()) { 29 | console.log("游戏胜利!"); 30 | over = true; 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /3. AMD和CMD/3-1. 浏览器端模块化的难题/笔记.md: -------------------------------------------------------------------------------- 1 | # 浏览器端模块化的难题 2 | 3 | **CommonJS的工作原理** 4 | 5 | 当使用```require(模块路径)```导入一个模块时,node会做以下两件事情(不考虑模块缓存): 6 | 7 | 1. 通过模块路径找到本机文件,并读取文件内容 8 | 2. 将文件中的代码放入到一个函数环境中执行,并将执行后module.exports的值作为require函数的返回结果 9 | 10 | 正是这两个步骤,使得CommonJS在node端可以良好的被支持 11 | 12 | 可以认为,**CommonJS是同步的**,必须要等到加载完文件并执行完代码后才能继续向后执行 13 | 14 | **当浏览器遇到CommonJS** 15 | 16 | 当想要把CommonJS放到浏览器端时,就遇到了一些挑战 17 | 18 | 1. 浏览器要加载JS文件,需要远程从服务器读取,而网络传输的效率远远低于node环境中读取本地文件的效率。由于CommonJS是同步的,这会极大的降低运行性能 19 | 2. 如果需要读取JS文件内容并把它放入到一个环境中执行,需要浏览器厂商的支持,可是浏览器厂商不愿意提供支持,最大的原因是CommonJS属于社区标准,并非官方标准 20 | 21 | **新的规范** 22 | 23 | 基于以上两点原因,浏览器无法支持模块化 24 | 25 | 可这并不代表模块化不能在浏览器中实现 26 | 27 | 要在浏览器中实现模块化,只要能解决上面的两个问题就行了 28 | 29 | 解决办法其实很简单: 30 | 31 | 1. 远程加载JS浪费了时间?做成异步即可,加载完成后调用一个回调就行了 32 | 2. 模块中的代码需要放置到函数中执行?编写模块时,直接放函数中就行了 33 | 34 | 基于这种简单有效的思路,出现了AMD和CMD规范,有效的解决了浏览器模块化的问题。 -------------------------------------------------------------------------------- /4. ES6模块化/4-2. 基本导入导出/笔记.md: -------------------------------------------------------------------------------- 1 | # 基本导入导出 2 | 3 | ## 模块的引入 4 | 5 | **注意:这一部分非模块化标准** 6 | 7 | 目前,浏览器使用以下方式引入一个ES6模块文件 8 | 9 | ```html 10 | 48 | 49 | -------------------------------------------------------------------------------- /2. CommonJS/2-2. CommonJS/笔记.md: -------------------------------------------------------------------------------- 1 | # CommonJS 2 | 3 | 在nodejs中,由于有且仅有一个入口文件(启动文件),而开发一个应用肯定会涉及到多个文件配合,因此,nodejs对模块化的需求比浏览器端要大的多 4 | 5 | ![](assets/2019-12-02-11-15-01.png) 6 | 7 | 由于nodejs刚刚发布的时候,前端没有统一的、官方的模块化规范,因此,它选择使用社区提供的CommonJS作为模块化规范 8 | 9 | 在学习CommonJS之前,首先认识两个重要的概念:**模块的导出**和**模块的导入** 10 | 11 | ## 模块的导出 12 | 13 | 要理解模块的导出,首先要理解模块的含义 14 | 15 | 什么是模块? 16 | 17 | 模块就是一个JS文件,它实现了一部分功能,并隐藏自己的内部实现,同时提供了一些接口供其他模块使用 18 | 19 | 模块有两个核心要素:**隐藏**和**暴露** 20 | 21 | 隐藏的,是自己内部的实现 22 | 23 | 暴露的,是希望外部使用的接口 24 | 25 | 任何一个正常的模块化标准,都应该默认隐藏模块中的所有实现,而通过一些语法或api调用来暴露接口 26 | 27 | **暴露接口的过程即模块的导出** 28 | 29 | ![](assets/2019-12-02-11-27-12.png) 30 | 31 | ## 模块的导入 32 | 33 | 当需要使用一个模块时,使用的是该模块暴露的部分(导出的部分),隐藏的部分是永远无法使用的。 34 | 35 | **当通过某种语法或api去使用一个模块时,这个过程叫做模块的导入** 36 | 37 | ## CommonJS规范 38 | 39 | CommonJS使用```exports```导出模块,```require```导入模块 40 | 41 | 具体规范如下: 42 | 43 | 1. 如果一个JS文件中存在```exports```或```require```,该JS文件是一个模块 44 | 2. 模块内的所有代码均为隐藏代码,包括全局变量、全局函数,这些全局的内容均不应该对全局变量造成任何污染 45 | 3. 如果一个模块需要暴露一些API提供给外部使用,需要通过```exports```导出,```exports```是一个空的对象,你可以为该对象添加任何需要导出的内容 46 | 4. 如果一个模块需要导入其他模块,通过```require```实现,```require```是一个函数,传入模块的路径即可返回该模块导出的整个内容 47 | 48 | ## nodejs对CommonJS的实现 49 | 50 | 为了实现CommonJS规范,nodejs对模块做出了以下处理 51 | 52 | 1. 为了保证高效的执行,仅加载必要的模块。nodejs只有执行到```require```函数时才会加载并执行模块 53 | 2. 为了隐藏模块中的代码,nodejs执行模块时,会将模块中的所有代码放置到一个函数中执行,以保证不污染全局变量。 54 | ```js 55 | (function(){ 56 | //模块中的代码 57 | })() 58 | ``` 59 | 60 | 3. 为了保证顺利的导出模块内容,nodejs做了以下处理 61 | 1. 在模块开始执行前,初始化一个值```module.exports = {}``` 62 | 2. ```module.exports```即模块的导出值 63 | 3. 为了方便开发者便捷的导出,nodejs在初始化完```module.exports```后,又声明了一个变量```exports = module.exports``` 64 | 65 | ```js 66 | (function(module){ 67 | module.exports = {}; 68 | var exports = module.exports; 69 | //模块中的代码 70 | return module.exports; 71 | })() 72 | ``` 73 | 4. 为了避免反复加载同一个模块,nodejs默认开启了模块缓存,如果加载的模块已经被加载过了,则会自动使用之前的导出结果 -------------------------------------------------------------------------------- /4. ES6模块化/4-5. ES6模块化练习/module/ui.js: -------------------------------------------------------------------------------- 1 | //该模块用于将地图显示到页面上 2 | import * as map from "./map.js"; 3 | 4 | var divContainer = document.getElementById("game"); 5 | var pieceWidth = 45; //每一个小块的宽度 6 | var pieceHeight = 45; //每一个小块的高度 7 | 8 | /** 9 | * 设置div的宽度 10 | */ 11 | function setDivContainer() { 12 | divContainer.style.width = pieceWidth * map.colNumber + "px"; 13 | divContainer.style.height = pieceHeight * map.rowNumber + "px"; 14 | } 15 | 16 | /** 17 | * 判断该行该列是否是正确位置 18 | * @param {*} row 19 | * @param {*} col 20 | */ 21 | function isCorrect(row, col) { 22 | for (var i = 0; i < map.correct.length; i++) { 23 | var point = map.correct[i];//拿到其中一个正确位置的坐标 24 | if (point.row === row && point.col === col) { 25 | return true; 26 | } 27 | } 28 | return false; 29 | 30 | // return map.correct.find(p => p.row === row && p.col === col) !== undefined; 31 | } 32 | 33 | /** 34 | * 根据行和列,创建一个div加入到容器 35 | * @param {*} row 36 | * @param {*} col 37 | */ 38 | function setOnePiece(row, col) { 39 | var value = map.content[row][col]; //取出地图相应位置的值 40 | var div = document.createElement("div"); 41 | div.className = "item"; 42 | //调整div的位置 43 | div.style.left = col * pieceWidth + "px"; 44 | div.style.top = row * pieceHeight + "px"; 45 | 46 | //当前位置是否是正确位置 47 | var correct = isCorrect(row, col); 48 | if (value === map.PLAYER) { 49 | div.classList.add("player"); 50 | } 51 | else if (value === map.WALL) { 52 | div.classList.add("wall"); 53 | } 54 | else if (value === map.BOX) { 55 | if (correct) { 56 | div.classList.add("correct-box"); 57 | } 58 | else { 59 | div.classList.add("box"); 60 | } 61 | } 62 | else { 63 | //空白 64 | if (correct) { 65 | div.classList.add("correct"); 66 | } 67 | else { 68 | return; //只是一个普通空白 69 | } 70 | } 71 | 72 | divContainer.appendChild(div); 73 | } 74 | 75 | /** 76 | * 根据地图在页面上设置相应的元素 77 | */ 78 | function setContent() { 79 | //1. 清空容器 80 | divContainer.innerHTML = ""; 81 | //2. 遍历地图内容,设置元素 82 | for (var row = 0; row < map.rowNumber; row++) { 83 | for (var col = 0; col < map.colNumber; col++) { 84 | setOnePiece(row, col); 85 | } 86 | } 87 | } 88 | 89 | /** 90 | * 该函数用于显示地图 91 | */ 92 | export default function () { 93 | //1. 设置div的宽高 94 | setDivContainer(); 95 | //2. 显示地图中的内容 96 | setContent(); 97 | } -------------------------------------------------------------------------------- /4. ES6模块化/4-5. ES6模块化练习/module/play.js: -------------------------------------------------------------------------------- 1 | import * as map from "./map.js"; 2 | 3 | /** 4 | * 按照指定的方向,让玩家移动一步 5 | * @param {*} direction left、right、up、down 6 | */ 7 | export function playerMove(direction) { 8 | var playerPoint = getPlayerPoint(); //得到玩家位置 9 | //得到玩家下一个位置的信息 10 | var nextInfo = getNextInfo(playerPoint.row, playerPoint.col, direction) 11 | 12 | //什么情况下,不能移动 13 | if (nextInfo.value === map.WALL) { 14 | return false; //下一个位置是墙 15 | } 16 | 17 | //能移动 18 | if (nextInfo.value === map.SPACE) { 19 | //下一个位置是空白 20 | exchange(playerPoint, nextInfo); 21 | return true; 22 | } 23 | else { 24 | //下一个位置是箱子 25 | //获取箱子的下一个位置 26 | var nextNextInfo = getNextInfo(nextInfo.row, nextInfo.col, direction) 27 | if (nextNextInfo.value === map.SPACE) { 28 | //可以移动 29 | exchange(nextInfo, nextNextInfo); 30 | exchange(playerPoint, nextInfo); 31 | return true; 32 | } 33 | else { 34 | return false; 35 | } 36 | } 37 | } 38 | 39 | /** 40 | * 根据当前地图内容,判断是否游戏胜利 41 | */ 42 | export function isWin() { 43 | //是否每个正确位置都有箱子 44 | for (var i = 0; i < map.correct.length; i++) { 45 | var point = map.correct[i]; 46 | if (map.content[point.row][point.col] !== map.BOX) { 47 | //该正确位置上没有箱子 48 | return false; 49 | } 50 | } 51 | return true; 52 | } 53 | 54 | function exchange(point1, point2) { 55 | var temp = map.content[point1.row][point1.col]; 56 | map.content[point1.row][point1.col] = map.content[point2.row][point2.col]; 57 | map.content[point2.row][point2.col] = temp; 58 | } 59 | 60 | /** 61 | * 得到玩家的位置 62 | */ 63 | function getPlayerPoint() { 64 | for (var row = 0; row < map.rowNumber; row++) { 65 | for (var col = 0; col < map.colNumber; col++) { 66 | if (map.content[row][col] === map.PLAYER) { 67 | return { 68 | row: row, 69 | col: col 70 | } 71 | } 72 | } 73 | } 74 | throw new Error("地图上居然没有玩家"); 75 | } 76 | 77 | /** 78 | * 得到某个位置在指定方向上的下一个位置的信息(第几行、第几列、内容是啥) 79 | * @param row 指定的行 80 | * @param col 指定的列 81 | * @param {*} direction 82 | */ 83 | function getNextInfo(row, col, direction) { 84 | if (direction === "left") { 85 | return { 86 | row: row, 87 | col: col - 1, 88 | value: map.content[row][col - 1] 89 | } 90 | } 91 | else if (direction === "right") { 92 | return { 93 | row: row, 94 | col: col + 1, 95 | value: map.content[row][col + 1] 96 | } 97 | } 98 | else if (direction === "up") { 99 | return { 100 | row: row - 1, 101 | col: col, 102 | value: map.content[row - 1][col] 103 | } 104 | } 105 | else { 106 | return { 107 | row: row + 1, 108 | col: col, 109 | value: map.content[row + 1][col] 110 | } 111 | } 112 | } -------------------------------------------------------------------------------- /1. 概述/1-1. JS模块化发展史/笔记.md: -------------------------------------------------------------------------------- 1 | # JavaScript 模块化发展史 {ignore} 2 | 3 | [toc] 4 | 5 | ## 第一阶段 6 | 7 | 在 JavaScript 语言刚刚诞生的时候,它仅仅用于实现页面中的一些小效果 8 | 9 | 那个时候,一个页面所用到的 JS 可能只有区区几百行的代码 10 | 11 | 在这种情况下,语言本身所存在的一些缺陷往往被大家有意的忽略,因为程序的规模实在太小,只要开发人员小心谨慎,往往不会造成什么问题 12 | 13 | 在这个阶段,也不存在专业的前端工程师,由于前端要做的事情实在太少,因此这一部分工作往往由后端工程师顺带完成 14 | 15 | 第一阶段发生的大事件: 16 | 17 | - 1996年,NetScape将JavaScript语言提交给欧洲的一个标准制定阻止ECMA(欧洲计算机制造商协会) 18 | - 1998年,NetScape在与微软浏览器IE的竞争中失利,宣布破产 19 | 20 | ## 第二阶段 21 | 22 | ajax的出现,逐渐改变了 JavaScript 在浏览器中扮演的角色。现在,它不仅可以实现小的效果,还可以和服务器之间进行交互,以更好的体验来改变数据 23 | 24 | JS代码的数量开始逐渐增长,从最初的几百行,到后来的几万行,前端程序逐渐变得复杂 25 | 26 | 后端开发者压力逐渐增加,致使一些公司开始招募专业的前端开发者 27 | 28 | 但此时,前端开发者的待遇远不及后端开发者,因为前端开发者承担的开发任务相对于后端开发来说,还是比较简单的,通过短短一个月的时间集训,就可以成为满足前端开发的需要 29 | 30 | 究其根本原因,是因为前端开发还有几个大的问题没有解决,这些问题都严重的制约了前端程序的规模进一步扩大: 31 | 32 | 1. **浏览器解释执行JS的速度太慢** 33 | 2. **用户端的电脑配置不足** 34 | 3. 更多的代码带来了全局变量污染、依赖关系混乱等问题 35 | 36 | 上面三个问题,就像是阿喀琉斯之踵,成为前端开发挥之不去的阴影和原罪。 37 | 38 | 在这个阶段,前端开发处在一个非常尴尬的境地,它在传统的开发模式和前后端分离之间无助的徘徊 39 | 40 | 第二阶段的大事件: 41 | 42 | 1. IE浏览器制霸市场后,几乎不再更新 43 | 2. ES4.0流产,导致JS语言10年间几乎毫无变化 44 | 3. 2008年ES5发布,仅解决了一些 JS API 不足的糟糕局面 45 | 46 | ## 第三阶段 47 | 48 | 时间继续向前推移,到了2008年,谷歌的 V8 引擎发布,将JS的执行速度推上了一个新的台阶,甚至可以和后端语言媲美。 49 | 50 | 摩尔定律持续发酵,个人电脑的配置开始飞跃 51 | 52 | 突然间,制约前端发展的两大问题得以解决,此时,只剩下最后一个问题还在负隅顽抗,即**全局变量污染和依赖混乱**的问题,解决了它,前端便可以突破一切障碍,未来无可限量。 53 | 54 | 于是,全世界的前端开发者在社区中激烈的讨论,想要为这个问题寻求解决之道...... 55 | 56 | 2008年,有一个名叫 Ryan Dahl 小伙子正在为一件事焦头烂额,它需要在服务器端手写一个高性能的web服务,该服务对于性能要求之高,以至于目前市面上已有的web服务产品都满足不了需求。 57 | 58 | 经过分析,它确定,如果要实现高性能,那么必须要尽可能的减少线程,而要减少线程,避免不了要实用异步的处理方案。 59 | 60 | 一开始,他打算自己实用C/C++语言来编写,可是这一过程实在太痛苦。 61 | 62 | 就在他一筹莫展的时候,谷歌 V8 引擎的发布引起了他的注意,他突然发现,JS不就是最好的实现web服务的语言吗?它天生就是单线程,并且是基于异步的!有了V8引擎的支撑,它的执行速度完全可以撑起一个服务器。而且V8是鼎鼎大名的谷歌公司发布的,谷歌一定会不断的优化V8,有这种又省钱又省力的好事,我干嘛还要自己去写呢? 63 | 64 | 于是,它基于开源的V8引擎,对源代码作了一些修改,便快速的完成了该项目。 65 | 66 | 2009年,Ryan推出了该web服务项目,命名为nodejs。 67 | 68 | 从此,JS第一次堂堂正正的入主后端,不再是必须附属于浏览器的“玩具”语言了。 69 | 70 | 也是从此刻开始,人们认识到,JS(ES)是一门真正的语言,它依附于运行环境(运行时)(宿主程序)而执行 71 | 72 | ![](assets/2019-11-28-15-45-47.png) 73 | 74 | nodejs的诞生,便把JS中的最后一个问题放到了台前,即**全局变量污染和依赖混乱**问题 75 | 76 | 要直到,nodejs是服务器端,如果不解决这个问题,分模块开发就无从实现,而模块化开发是所有后端程序必不可少的内容 77 | 78 | 经过社区的激烈讨论,最终,形成了一个模块化方案,即鼎鼎大名的CommonJS,该方案,彻底解决了全局变量污染和依赖混乱的问题 79 | 80 | 该方案一出,立即被nodejs支持,于是,nodejs成为了第一个为JS语言实现模块化的平台,为前端接下来的迅猛发展奠定了实践基础 81 | 82 | 该阶段发生的大事件: 83 | 84 | - 2008年,V8发布 85 | - IE的市场逐步被 firefox 和 chrome 蚕食,现已无力回天 86 | - 2009年,nodejs发布,并附带commonjs模块化标准 87 | 88 | ## 第四阶段 89 | 90 | CommonJS的出现打开了前端开发者的思路 91 | 92 | 既然后端可以使用模块化的JS,作为JS语言的老东家浏览器为什么不行呢? 93 | 94 | 于是,开始有人想办法把CommonJS运用到浏览器中 95 | 96 | 可是这里面存在诸多的困难(课程中详解) 97 | 98 | 办法总比困难多,有些开发者就想,既然CommonJS运用到浏览器困难,我们干嘛不自己重新定一个模块化的标准出来,难道就一定要用CommonJS标准吗? 99 | 100 | 于是很快,AMD规范出炉,它解决的问题和CommonJS一样,但是可以更好的适应浏览器环境 101 | 102 | 相继的,CMD规范出炉,它对AMD规范进行了改进 103 | 104 | 这些行为,都受到了ECMA官方的密切关注...... 105 | 106 | 2015年,ES6发布,它提出了官方的模块化解决方案 —— ES6 模块化 107 | 108 | 从此以后,模块化成为了JS本身特有的性质,这门语言终于有了和其他语言较量的资本,成为了可以编写大型应用的正式语言 109 | 110 | 于此同时,很多开发者、技术厂商早已预见到JS的无穷潜力,于是有了下面的故事 111 | 112 | - 既然JS也能编写大型应用,那么自然也需要像其他语言那样有解决复杂问题的开发框架 113 | - Angular、React、Vue等前端开发框架出现 114 | - Express、Koa等后端开发框架出现 115 | - 各种后端数据库驱动出现 116 | - 要开发大型应用,自然少不了各种实用的第三方库的支持 117 | - npm包管理器出现,实用第三方库变得极其方便 118 | - webpack等构建工具出现,专门用于打包和部署 119 | - 既然JS可以放到服务器环境,为什么不能放到其他终端环境呢? 120 | - Electron发布,可以使用JS语言开发桌面应用程序 121 | - RN和Vuex等技术发布,可以使用JS语言编写移动端应用程序 122 | - 各种小程序出现,可以使用JS编写依附于其他应用的小程序 123 | - 目前还有很多厂商致力于将JS应用到各种其他的终端设备,最终形成大前端生态 124 | 125 | > 可以看到,模块化的出现,是JS通向大型应用的基石,学习好模块化,变具备了编写大型应用的基本功。 -------------------------------------------------------------------------------- /3. AMD和CMD/3-3. CMD/js/sea.js: -------------------------------------------------------------------------------- 1 | !function (a, b) { function c(a) { return function (b) { return {}.toString.call(b) == "[object " + a + "]" } } function d() { return B++ } function e(a) { return a.match(E)[0] } function f(a) { for (a = a.replace(F, "/"), a = a.replace(H, "$1/"); a.match(G);)a = a.replace(G, "/"); return a } function g(a) { var b = a.length - 1, c = a.charCodeAt(b); return 35 === c ? a.substring(0, b) : ".js" === a.substring(b - 2) || a.indexOf("?") > 0 || 47 === c ? a : a + ".js" } function h(a) { var b = v.alias; return b && x(b[a]) ? b[a] : a } function i(a) { var b = v.paths, c; return b && (c = a.match(I)) && x(b[c[1]]) && (a = b[c[1]] + c[2]), a } function j(a) { var b = v.vars; return b && a.indexOf("{") > -1 && (a = a.replace(J, function (a, c) { return x(b[c]) ? b[c] : a })), a } function k(a) { var b = v.map, c = a; if (b) for (var d = 0, e = b.length; e > d; d++) { var f = b[d]; if (c = z(f) ? f(a) || a : a.replace(f[0], f[1]), c !== a) break } return c } function l(a, b) { var c, d = a.charCodeAt(0); if (K.test(a)) c = a; else if (46 === d) c = (b ? e(b) : v.cwd) + a; else if (47 === d) { var g = v.cwd.match(L); c = g ? g[0] + a.substring(1) : a } else c = v.base + a; return 0 === c.indexOf("//") && (c = location.protocol + c), f(c) } function m(a, b) { if (!a) return ""; a = h(a), a = i(a), a = h(a), a = j(a), a = h(a), a = g(a), a = h(a); var c = l(a, b); return c = h(c), c = k(c) } function n(a) { return a.hasAttribute ? a.src : a.getAttribute("src", 4) } function o(a, b, c, d) { var e; try { importScripts(a) } catch (f) { e = f } b(e) } function p(a, b, c, d) { var e = Z.createElement("script"); c && (e.charset = c), A(d) || e.setAttribute("crossorigin", d), q(e, b, a), e.async = !0, e.src = a, ca = e, ba ? aa.insertBefore(e, ba) : aa.appendChild(e), ca = null } function q(a, b, c) { function d(c) { a.onload = a.onerror = a.onreadystatechange = null, v.debug || aa.removeChild(a), a = null, b(c) } var e = "onload" in a; e ? (a.onload = d, a.onerror = function () { D("error", { uri: c, node: a }), d(!0) }) : a.onreadystatechange = function () { /loaded|complete/.test(a.readyState) && d() } } function r() { if (ca) return ca; if (da && "interactive" === da.readyState) return da; for (var a = aa.getElementsByTagName("script"), b = a.length - 1; b >= 0; b--) { var c = a[b]; if ("interactive" === c.readyState) return da = c } } function s(a) { var b = []; return a.replace(fa, "").replace(ea, function (a, c, d) { d && b.push(d) }), b } function t(a, b) { this.uri = a, this.dependencies = b || [], this.deps = {}, this.status = 0, this._entry = [] } if (!a.seajs) { var u = a.seajs = { version: "3.0.3" }, v = u.data = {}, w = c("Object"), x = c("String"), y = Array.isArray || c("Array"), z = c("Function"), A = c("Undefined"), B = 0, C = v.events = {}; u.on = function (a, b) { var c = C[a] || (C[a] = []); return c.push(b), u }, u.off = function (a, b) { if (!a && !b) return C = v.events = {}, u; var c = C[a]; if (c) if (b) for (var d = c.length - 1; d >= 0; d--)c[d] === b && c.splice(d, 1); else delete C[a]; return u }; var D = u.emit = function (a, b) { var c = C[a]; if (c) { c = c.slice(); for (var d = 0, e = c.length; e > d; d++)c[d](b) } return u }, E = /[^?#]*\//, F = /\/\.\//g, G = /\/[^\/]+\/\.\.\//, H = /([^:\/])\/+\//g, I = /^([^\/:]+)(\/.+)$/, J = /{([^{]+)}/g, K = /^\/\/.|:\//, L = /^.*?\/\/.*?\//; u.resolve = m; var M = "undefined" == typeof window && "undefined" != typeof importScripts && z(importScripts), N = /^(about|blob):/, O, P, Q = !location.href || N.test(location.href) ? "" : e(location.href); if (M) { var R; try { var S = Error(); throw S } catch (T) { R = T.stack.split("\n") } R.shift(); for (var U, V = /.*?((?:http|https|file)(?::\/{2}[\w]+)(?:[\/|\.]?)(?:[^\s"]*)).*?/i, W = /(.*?):\d+:\d+\)?$/; R.length > 0;) { var X = R.shift(); if (U = V.exec(X), null != U) break } var Y; if (null != U) var Y = W.exec(U[1])[1]; P = Y, O = e(Y || Q), "" === Q && (Q = O) } else { var Z = document, $ = Z.scripts, _ = Z.getElementById("seajsnode") || $[$.length - 1]; P = n(_), O = e(P || Q) } if (M) u.request = o; else { var Z = document, aa = Z.head || Z.getElementsByTagName("head")[0] || Z.documentElement, ba = aa.getElementsByTagName("base")[0], ca; u.request = p } var da, ea = /"(?:\\"|[^"])*"|'(?:\\'|[^'])*'|\/\*[\S\s]*?\*\/|\/(?:\\\/|[^\/\r\n])+\/(?=[^\/])|\/\/.*|\.\s*require|(?:^|[^$])\brequire\s*\(\s*(["'])(.+?)\1\s*\)/g, fa = /\\\\/g, ga = u.cache = {}, ha, ia = {}, ja = {}, ka = {}, la = t.STATUS = { FETCHING: 1, SAVED: 2, LOADING: 3, LOADED: 4, EXECUTING: 5, EXECUTED: 6, ERROR: 7 }; t.prototype.resolve = function () { for (var a = this, b = a.dependencies, c = [], d = 0, e = b.length; e > d; d++)c[d] = t.resolve(b[d], a.uri); return c }, t.prototype.pass = function () { for (var a = this, b = a.dependencies.length, c = 0; c < a._entry.length; c++) { for (var d = a._entry[c], e = 0, f = 0; b > f; f++) { var g = a.deps[a.dependencies[f]]; g.status < la.LOADED && !d.history.hasOwnProperty(g.uri) && (d.history[g.uri] = !0, e++ , g._entry.push(d), g.status === la.LOADING && g.pass()) } e > 0 && (d.remain += e - 1, a._entry.shift(), c--) } }, t.prototype.load = function () { var a = this; if (!(a.status >= la.LOADING)) { a.status = la.LOADING; var c = a.resolve(); D("load", c); for (var d = 0, e = c.length; e > d; d++)a.deps[a.dependencies[d]] = t.get(c[d]); if (a.pass(), a._entry.length) return a.onload(), b; var f = {}, g; for (d = 0; e > d; d++)g = ga[c[d]], g.status < la.FETCHING ? g.fetch(f) : g.status === la.SAVED && g.load(); for (var h in f) f.hasOwnProperty(h) && f[h]() } }, t.prototype.onload = function () { var a = this; a.status = la.LOADED; for (var b = 0, c = (a._entry || []).length; c > b; b++) { var d = a._entry[b]; 0 === --d.remain && d.callback() } delete a._entry }, t.prototype.error = function () { var a = this; a.onload(), a.status = la.ERROR }, t.prototype.exec = function () { function a(b) { var d = c.deps[b] || t.get(a.resolve(b)); if (d.status == la.ERROR) throw Error("module was broken: " + d.uri); return d.exec() } var c = this; if (c.status >= la.EXECUTING) return c.exports; if (c.status = la.EXECUTING, c._entry && !c._entry.length && delete c._entry, !c.hasOwnProperty("factory")) return c.non = !0, b; var e = c.uri; a.resolve = function (a) { return t.resolve(a, e) }, a.async = function (b, c) { return t.use(b, c, e + "_async_" + d()), a }; var f = c.factory, g = z(f) ? f.call(c.exports = {}, a, c.exports, c) : f; return g === b && (g = c.exports), delete c.factory, c.exports = g, c.status = la.EXECUTED, D("exec", c), c.exports }, t.prototype.fetch = function (a) { function c() { u.request(g.requestUri, g.onRequest, g.charset, g.crossorigin) } function d(a) { delete ia[h], ja[h] = !0, ha && (t.save(f, ha), ha = null); var b, c = ka[h]; for (delete ka[h]; b = c.shift();)a === !0 ? b.error() : b.load() } var e = this, f = e.uri; e.status = la.FETCHING; var g = { uri: f }; D("fetch", g); var h = g.requestUri || f; return !h || ja.hasOwnProperty(h) ? (e.load(), b) : ia.hasOwnProperty(h) ? (ka[h].push(e), b) : (ia[h] = !0, ka[h] = [e], D("request", g = { uri: f, requestUri: h, onRequest: d, charset: z(v.charset) ? v.charset(h) : v.charset, crossorigin: z(v.crossorigin) ? v.crossorigin(h) : v.crossorigin }), g.requested || (a ? a[g.requestUri] = c : c()), b) }, t.resolve = function (a, b) { var c = { id: a, refUri: b }; return D("resolve", c), c.uri || u.resolve(c.id, b) }, t.define = function (a, c, d) { var e = arguments.length; 1 === e ? (d = a, a = b) : 2 === e && (d = c, y(a) ? (c = a, a = b) : c = b), !y(c) && z(d) && (c = b === s ? [] : s("" + d)); var f = { id: a, uri: t.resolve(a), deps: c, factory: d }; if (!M && !f.uri && Z.attachEvent && b !== r) { var g = r(); g && (f.uri = g.src) } D("define", f), f.uri ? t.save(f.uri, f) : ha = f }, t.save = function (a, b) { var c = t.get(a); c.status < la.SAVED && (c.id = b.id || a, c.dependencies = b.deps || [], c.factory = b.factory, c.status = la.SAVED, D("save", c)) }, t.get = function (a, b) { return ga[a] || (ga[a] = new t(a, b)) }, t.use = function (b, c, d) { var e = t.get(d, y(b) ? b : [b]); e._entry.push(e), e.history = {}, e.remain = 1, e.callback = function () { for (var b = [], d = e.resolve(), f = 0, g = d.length; g > f; f++)b[f] = ga[d[f]].exec(); c && c.apply(a, b), delete e.callback, delete e.history, delete e.remain, delete e._entry }, e.load() }, u.use = function (a, b) { return t.use(a, b, v.cwd + "_use_" + d()), u }, t.define.cmd = {}, a.define = t.define, u.Module = t, v.fetchedList = ja, v.cid = d, u.require = function (a) { var b = t.get(t.resolve(a)); return b.status < la.EXECUTING && (b.onload(), b.exec()), b.exports }, v.base = O, v.dir = O, v.loader = P, v.cwd = Q, v.charset = "utf-8", u.config = function (a) { for (var b in a) { var c = a[b], d = v[b]; if (d && w(d)) for (var e in c) d[e] = c[e]; else y(d) ? c = d.concat(c) : "base" === b && ("/" !== c.slice(-1) && (c += "/"), c = l(c)), v[b] = c } return D("config", a), u } } }(this); 2 | -------------------------------------------------------------------------------- /4. ES6模块化/4-4. ES6模块化的其他细节/笔记.html: -------------------------------------------------------------------------------- 1 | 2 | 笔记 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 267 | 268 | 269 |
270 |

ES6模块化的其他细节

271 | 272 |
    273 |
  1. 尽量导出不可变值
  2. 274 |
275 |

当导出一个内容时,尽量保证该内容是不可变的(大部分情况都是如此)

276 |

因为,虽然导入后,无法更改导入内容,但是在导入的模块内部却有可能发生更改,这将导致一些无法预料的事情发生

277 |
    278 |
  1. 可以使用无绑定的导入用于执行一些初始化代码
  2. 279 |
280 |

如果我们只是想执行模块中的一些代码,而不需要导入它的任何内容,可以使用无绑定的导入:

281 |
import "模块路径"
282 | 
    283 |
  1. 可以使用绑定再导出,来重新导出来自另一个模块的内容
  2. 284 |
285 |

有的时候,我们可能需要用一个模块封装多个模块,然后有选择的将多个模块的内容分别导出,可以使用下面的语法轻松完成

286 |
export {绑定的标识符} from "模块路径"
287 | 

288 | 289 |
290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | -------------------------------------------------------------------------------- /4. ES6模块化/4-3. 默认导入导出/笔记.html: -------------------------------------------------------------------------------- 1 | 2 | 笔记 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 267 | 268 | 269 |
270 |

默认导入导出

271 | 272 |

273 |

默认导出

274 | 275 |

每个模块,除了允许有多个基本导出之外,还允许有一个默认导出

276 |

默认导出类似于CommonJS中的module.exports,由于只有一个,因此无需具名

277 |

具体的语法是

278 |
export default 默认导出的数据
279 | 

280 |
export {默认导出的数据 as default}
281 | 

由于每个模块仅允许有一个默认导出,因此,每个模块不能出现多个默认导出语句

282 |

默认导入

283 | 284 |

需要想要导入一个模块的默认导出,需要使用下面的语法

285 |
import 接收变量名 from "模块路径"
286 | 

类似于CommonJS中的

287 |
var 接收变量名 = require("模块路径")
288 | 

由于默认导入时变量名是自行定义的,因此没有别名一说

289 |

如果希望同时导入某个模块的默认导出和基本导出,可以使用下面的语法

290 |
import 接收默认导出的变量, {接收基本导出的变量} from "模块路径"
291 | 

注:如果使用*号,会将所有基本导出和默认导出聚合到一个对象中,默认导出会作为属性default存在

292 | 293 |
294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | -------------------------------------------------------------------------------- /3. AMD和CMD/3-1. 浏览器端模块化的难题/笔记.html: -------------------------------------------------------------------------------- 1 | 2 | 笔记 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 267 | 268 | 269 |
270 |

浏览器端模块化的难题

271 | 272 |

CommonJS的工作原理

273 |

当使用require(模块路径)导入一个模块时,node会做以下两件事情(不考虑模块缓存):

274 |
    275 |
  1. 通过模块路径找到本机文件,并读取文件内容
  2. 276 |
  3. 将文件中的代码放入到一个函数环境中执行,并将执行后module.exports的值作为require函数的返回结果
  4. 277 |
278 |

正是这两个步骤,使得CommonJS在node端可以良好的被支持

279 |

可以认为,CommonJS是同步的,必须要等到加载完文件并执行完代码后才能继续向后执行

280 |

当浏览器遇到CommonJS

281 |

当想要把CommonJS放到浏览器端时,就遇到了一些挑战

282 |
    283 |
  1. 浏览器要加载JS文件,需要远程从服务器读取,而网络传输的效率远远低于node环境中读取本地文件的效率。由于CommonJS是同步的,这会极大的降低运行性能
  2. 284 |
  3. 如果需要读取JS文件内容并把它放入到一个环境中执行,需要浏览器厂商的支持,可是浏览器厂商不愿意提供支持,最大的原因是CommonJS属于社区标准,并非官方标准
  4. 285 |
286 |

新的规范

287 |

基于以上两点原因,浏览器无法支持模块化

288 |

可这并不代表模块化不能在浏览器中实现

289 |

要在浏览器中实现模块化,只要能解决上面的两个问题就行了

290 |

解决办法其实很简单:

291 |
    292 |
  1. 远程加载JS浪费了时间?做成异步即可,加载完成后调用一个回调就行了
  2. 293 |
  3. 模块中的代码需要放置到函数中执行?编写模块时,直接放函数中就行了
  4. 294 |
295 |

基于这种简单有效的思路,出现了AMD和CMD规范,有效的解决了浏览器模块化的问题。

296 | 297 |
298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | -------------------------------------------------------------------------------- /4. ES6模块化/4-2. 基本导入导出/笔记.html: -------------------------------------------------------------------------------- 1 | 2 | 笔记 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 267 | 268 | 269 |
270 |

基本导入导出

271 | 272 |

模块的引入

273 | 274 |

注意:这一部分非模块化标准

275 |

目前,浏览器使用以下方式引入一个ES6模块文件

276 |
<script src="入口文件" type="module">
277 | 

模块的基本导出和导入

278 | 279 |

ES6中的模块导入导出分为两种:

280 |
    281 |
  1. 基本导入导出
  2. 282 |
  3. 默认导入导出
  4. 283 |
284 |

285 |

基本导出

286 | 287 |

类似于 exports.xxx = xxxx

288 |

基本导出可以有多个,每个必须有名称

289 |

基本导出的语法如下:

290 |
export 声明表达式
291 | 

292 |
export {具名符号}
293 | 

由于基本导出必须具有名称,所以要求导出内容必须跟上声明表达式具名符号

294 |

基本导入

295 | 296 |

由于使用的是依赖预加载,因此,导入任何其他模块,导入代码必须放置到所有代码之前

297 |

对于基本导出,如果要进行导入,使用下面的代码

298 |
import {导入的符号列表} from "模块路径" 
299 | 

注意以下细节:

300 | 305 | 306 |
307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | -------------------------------------------------------------------------------- /2. CommonJS/2-2. CommonJS/笔记.html: -------------------------------------------------------------------------------- 1 | 2 | 笔记 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 267 | 268 | 269 |
270 |

CommonJS

271 | 272 |

在nodejs中,由于有且仅有一个入口文件(启动文件),而开发一个应用肯定会涉及到多个文件配合,因此,nodejs对模块化的需求比浏览器端要大的多

273 |

274 |

由于nodejs刚刚发布的时候,前端没有统一的、官方的模块化规范,因此,它选择使用社区提供的CommonJS作为模块化规范

275 |

在学习CommonJS之前,首先认识两个重要的概念:模块的导出模块的导入

276 |

模块的导出

277 | 278 |

要理解模块的导出,首先要理解模块的含义

279 |

什么是模块?

280 |

模块就是一个JS文件,它实现了一部分功能,并隐藏自己的内部实现,同时提供了一些接口供其他模块使用

281 |

模块有两个核心要素:隐藏暴露

282 |

隐藏的,是自己内部的实现

283 |

暴露的,是希望外部使用的接口

284 |

任何一个正常的模块化标准,都应该默认隐藏模块中的所有实现,而通过一些语法或api调用来暴露接口

285 |

暴露接口的过程即模块的导出

286 |

287 |

模块的导入

288 | 289 |

当需要使用一个模块时,使用的是该模块暴露的部分(导出的部分),隐藏的部分是永远无法使用的。

290 |

当通过某种语法或api去使用一个模块时,这个过程叫做模块的导入

291 |

CommonJS规范

292 | 293 |

CommonJS使用exports导出模块,require导入模块

294 |

具体规范如下:

295 |
    296 |
  1. 如果一个JS文件中存在exportsrequire,该JS文件是一个模块
  2. 297 |
  3. 模块内的所有代码均为隐藏代码,包括全局变量、全局函数,这些全局的内容均不应该对全局变量造成任何污染
  4. 298 |
  5. 如果一个模块需要暴露一些API提供给外部使用,需要通过exports导出,exports是一个空的对象,你可以为该对象添加任何需要导出的内容
  6. 299 |
  7. 如果一个模块需要导入其他模块,通过require实现,require是一个函数,传入模块的路径即可返回该模块导出的整个内容
  8. 300 |
301 |

nodejs对CommonJS的实现

302 | 303 |

为了实现CommonJS规范,nodejs对模块做出了以下处理

304 |
    305 |
  1. 306 |

    为了保证高效的执行,仅加载必要的模块。nodejs只有执行到require函数时才会加载并执行模块

    307 |
  2. 308 |
  3. 309 |

    为了隐藏模块中的代码,nodejs执行模块时,会将模块中的所有代码放置到一个函数中执行,以保证不污染全局变量。

    310 |
     (function(){
    311 |      //模块中的代码
    312 |  })()
    313 | 
  4. 314 |
  5. 315 |

    为了保证顺利的导出模块内容,nodejs做了以下处理

    316 |
      317 |
    1. 在模块开始执行前,初始化一个值module.exports = {}
    2. 318 |
    3. module.exports即模块的导出值
    4. 319 |
    5. 为了方便开发者便捷的导出,nodejs在初始化完module.exports后,又声明了一个变量exports = module.exports
    6. 320 |
    321 |
     (function(module){
    322 |      module.exports = {};
    323 |      var exports = module.exports;
    324 |      //模块中的代码
    325 |      return module.exports;
    326 |  })()
    327 | 
  6. 328 |
  7. 329 |

    为了避免反复加载同一个模块,nodejs默认开启了模块缓存,如果加载的模块已经被加载过了,则会自动使用之前的导出结果

    330 |
  8. 331 |
332 | 333 |
334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | -------------------------------------------------------------------------------- /1. 概述/1-1. JS模块化发展史/笔记.html: -------------------------------------------------------------------------------- 1 | 2 | 笔记 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 267 | 268 | 269 |
270 |

JavaScript 模块化发展史

271 | 272 | 278 |

第一阶段

279 | 280 |

在 JavaScript 语言刚刚诞生的时候,它仅仅用于实现页面中的一些小效果

281 |

那个时候,一个页面所用到的 JS 可能只有区区几百行的代码

282 |

在这种情况下,语言本身所存在的一些缺陷往往被大家有意的忽略,因为程序的规模实在太小,只要开发人员小心谨慎,往往不会造成什么问题

283 |

在这个阶段,也不存在专业的前端工程师,由于前端要做的事情实在太少,因此这一部分工作往往由后端工程师顺带完成

284 |

第一阶段发生的大事件:

285 | 289 |

第二阶段

290 | 291 |

ajax的出现,逐渐改变了 JavaScript 在浏览器中扮演的角色。现在,它不仅可以实现小的效果,还可以和服务器之间进行交互,以更好的体验来改变数据

292 |

JS代码的数量开始逐渐增长,从最初的几百行,到后来的几万行,前端程序逐渐变得复杂

293 |

后端开发者压力逐渐增加,致使一些公司开始招募专业的前端开发者

294 |

但此时,前端开发者的待遇远不及后端开发者,因为前端开发者承担的开发任务相对于后端开发来说,还是比较简单的,通过短短一个月的时间集训,就可以成为满足前端开发的需要

295 |

究其根本原因,是因为前端开发还有几个大的问题没有解决,这些问题都严重的制约了前端程序的规模进一步扩大:

296 |
    297 |
  1. 浏览器解释执行JS的速度太慢
  2. 298 |
  3. 用户端的电脑配置不足
  4. 299 |
  5. 更多的代码带来了全局变量污染、依赖关系混乱等问题
  6. 300 |
301 |

上面三个问题,就像是阿喀琉斯之踵,成为前端开发挥之不去的阴影和原罪。

302 |

在这个阶段,前端开发处在一个非常尴尬的境地,它在传统的开发模式和前后端分离之间无助的徘徊

303 |

第二阶段的大事件:

304 |
    305 |
  1. IE浏览器制霸市场后,几乎不再更新
  2. 306 |
  3. ES4.0流产,导致JS语言10年间几乎毫无变化
  4. 307 |
  5. 2008年ES5发布,仅解决了一些 JS API 不足的糟糕局面
  6. 308 |
309 |

第三阶段

310 | 311 |

时间继续向前推移,到了2008年,谷歌的 V8 引擎发布,将JS的执行速度推上了一个新的台阶,甚至可以和后端语言媲美。

312 |

摩尔定律持续发酵,个人电脑的配置开始飞跃

313 |

突然间,制约前端发展的两大问题得以解决,此时,只剩下最后一个问题还在负隅顽抗,即全局变量污染和依赖混乱的问题,解决了它,前端便可以突破一切障碍,未来无可限量。

314 |

于是,全世界的前端开发者在社区中激烈的讨论,想要为这个问题寻求解决之道......

315 |

2008年,有一个名叫 Ryan Dahl 小伙子正在为一件事焦头烂额,它需要在服务器端手写一个高性能的web服务,该服务对于性能要求之高,以至于目前市面上已有的web服务产品都满足不了需求。

316 |

经过分析,它确定,如果要实现高性能,那么必须要尽可能的减少线程,而要减少线程,避免不了要实用异步的处理方案。

317 |

一开始,他打算自己实用C/C++语言来编写,可是这一过程实在太痛苦。

318 |

就在他一筹莫展的时候,谷歌 V8 引擎的发布引起了他的注意,他突然发现,JS不就是最好的实现web服务的语言吗?它天生就是单线程,并且是基于异步的!有了V8引擎的支撑,它的执行速度完全可以撑起一个服务器。而且V8是鼎鼎大名的谷歌公司发布的,谷歌一定会不断的优化V8,有这种又省钱又省力的好事,我干嘛还要自己去写呢?

319 |

于是,它基于开源的V8引擎,对源代码作了一些修改,便快速的完成了该项目。

320 |

2009年,Ryan推出了该web服务项目,命名为nodejs。

321 |

从此,JS第一次堂堂正正的入主后端,不再是必须附属于浏览器的“玩具”语言了。

322 |

也是从此刻开始,人们认识到,JS(ES)是一门真正的语言,它依附于运行环境(运行时)(宿主程序)而执行

323 |

324 |

nodejs的诞生,便把JS中的最后一个问题放到了台前,即全局变量污染和依赖混乱问题

325 |

要直到,nodejs是服务器端,如果不解决这个问题,分模块开发就无从实现,而模块化开发是所有后端程序必不可少的内容

326 |

经过社区的激烈讨论,最终,形成了一个模块化方案,即鼎鼎大名的CommonJS,该方案,彻底解决了全局变量污染和依赖混乱的问题

327 |

该方案一出,立即被nodejs支持,于是,nodejs成为了第一个为JS语言实现模块化的平台,为前端接下来的迅猛发展奠定了实践基础

328 |

该阶段发生的大事件:

329 | 334 |

第四阶段

335 | 336 |

CommonJS的出现打开了前端开发者的思路

337 |

既然后端可以使用模块化的JS,作为JS语言的老东家浏览器为什么不行呢?

338 |

于是,开始有人想办法把CommonJS运用到浏览器中

339 |

可是这里面存在诸多的困难(课程中详解)

340 |

办法总比困难多,有些开发者就想,既然CommonJS运用到浏览器困难,我们干嘛不自己重新定一个模块化的标准出来,难道就一定要用CommonJS标准吗?

341 |

于是很快,AMD规范出炉,它解决的问题和CommonJS一样,但是可以更好的适应浏览器环境

342 |

相继的,CMD规范出炉,它对AMD规范进行了改进

343 |

这些行为,都受到了ECMA官方的密切关注......

344 |

2015年,ES6发布,它提出了官方的模块化解决方案 —— ES6 模块化

345 |

从此以后,模块化成为了JS本身特有的性质,这门语言终于有了和其他语言较量的资本,成为了可以编写大型应用的正式语言

346 |

于此同时,很多开发者、技术厂商早已预见到JS的无穷潜力,于是有了下面的故事

347 | 370 |
371 |

可以看到,模块化的出现,是JS通向大型应用的基石,学习好模块化,变具备了编写大型应用的基本功。

372 |
373 | 374 |
375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | --------------------------------------------------------------------------------