知识点【JavaScript模块化】
JavaScript模块化历程
JavaScript发展变迁大概是一下几个步骤:
工具(浏览器兼容)
组件(功能模块)
框架(功能模块组织)
应用(业务模块组织)
但是经过了长长的后天努力过程JavaScript不断被类聚抽象,以更好的组织业务逻辑。从另一个角度而言,他也道出了JavaScript先天就缺乏的一项功能:模块
虽然W3C组织对HTML5规范推进以及各大厂对规范的大力支持,但是对于JavaScript本身而言,它的规范依然是薄弱的,它还有以下缺陷:
没有标准模块系统
标准库少(ECMAScript仅定义了部分核心库)
没有标准接口(JavaScript几乎没有定义过如WEB服务器数据库操作之类的标准统一接口)
缺乏包管理系统
CommonJS规范
CommonJS规范的提出,主要为了弥补JavaScript没有标准的缺陷,以达到想Python、Ruby和Java具备开发大型应用的基础能力,而不是停留在小脚本程序的阶段。
它的使用和定义也非常简单
CommonJS的模块规范
1 模块定义
// example.js
var x =5;
var addx = function (value){
return value + x;
}
module.exports.x = x;
module.exports.addx = addx;
定义关键字是exports这个module是什么意思呢:在CommonJS定义了每个文件都一个模块,也就是说module代表文件本身
2 模块引用
var example = require('./example.js');
console.log(example.x); //
console.log(example.addx(1)); //
CommonJS模块特点如下:
所有代码都运行在模块作用域,不会污染全局作用域。
模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
模块加载的顺序,按照其在代码中出现的顺序。
3 看图
用一个图很明显的看出它们之间的引用关系

模块的实现
在Node中引入模块,需要经历3个步骤
1、路径分析
2、文件定位
3、编译执行
在Node中模块分为两类:一类是Node提供的模块,称为核心模块;另一类是用户编写的模块称为文件模块。
ES6 Module
ES6 模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。
// CommonJS模块
let { stat, exists, readFile } = require('fs'); // 等同于
let _fs = require('fs');
let stat = _fs.stat;
let exists = _fs.exists;
let readfile = _fs.readfile;
上面代码的实质是整体加载fs模块(即加载fs的所有方法),生成一个对象(_fs),然后再从这个对象上面读取3个方法。这种加载称为“运行时加载”,因为只有运行时才能得到这个对象,导致完全没办法在编译时做“静态优化”。
ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。
与CommonJS思想类似
1 模块定义
// profile.js
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;
上面代码是profile.js文件,保存了用户信息。ES6 将其视为一个模块,里面用export命令对外部输出了三个变量。
export的写法,除了像上面这样,还有另外一种。
// profile.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958; export {firstName, lastName, year};
通常情况下,export输出的变量就是本来的名字,但是可以使用as关键字重命名。
function v1() { ... }
function v2() { ... }
export {
v1 as streamV1,
v2 as streamV2,
v2 as streamLatestVersion
};
注意规范:
export命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系。
// 报错
export 1; // 报错
var m = 1;
export m;
上面两种写法都会报错,因为没有提供对外的接口。第一种写法直接输出1,第二种写法通过变量m,还是直接输出1。1只是一个值,不是接口。正确的写法是下面这样。
// 写法一
export var m = 1; // 写法二
var m = 1;
export {m}; // 写法三
var n = 1;
export {n as m};
function和class的输出,也必须遵守这样的写法。
// 报错
function f() {}
export f; // 正确
export function f() {}; // 正确
function f() {}
export {f};
另外,export语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值。
2 模块引用
// a.js
let a = 18;
let funcA = function () {
console.log('module A')
}; // 提供一个对外的借口并输出a变量和funcA方法
export {a, funcA}
引用
import {a, funcA} from "./a";
// 通过import 引入里面的变量和方法
console.log(a);
console.log(funcA());
引用的时候可以设置别名
import {a as aValue, funcA} from "./a";
// 通过import 引入里面的变量和方法
console.log(aValue);
console.log(funcA());
3 export default命令
从前面的例子可以看出,使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载。但是,用户肯定希望快速上手,未必愿意阅读文档,去了解模块有哪些属性和方法。
为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。
本质上,export default就是输出一个叫做default的变量或方法,然后系统允许你为它取任意名字
// export-default.js
export default function () {
console.log('foo');
}
然后你可以随便命名
// import-default.js
import customName from './export-default';
customName(); // 'foo'
但是正常引入模块的情况下你必须指定你要引入的变量或者方法,像下面一样:
import {funcA} from "./a.js"; // 这里你在引用的时候你必须知道a.js中定义的方法的名字
比较下正常和export default不同
// 第一组
export default function crc32() { // 输出
// ...
} import crc32 from 'crc32'; // 输入 // 第二组
export function crc32() { // 输出
// ...
}; import {crc32} from 'crc32'; // 输入
Module 的加载实现
上面是模块的语法,接下来看看如何在浏览器和Node中加载ES6模块
浏览器加载ES6模块
在 HTML 网页中,浏览器通过<script>标签加载 JavaScript 脚本
<!-- 页面内嵌的脚本 -->
<script type="application/javascript">
// module code
</script> <!-- 外部脚本 -->
<script type="application/javascript" src="path/to/myModule.js">
</script>
上面代码中,由于浏览器脚本的默认语言是 JavaScript,因此type="application/javascript"可以省略。
同样如果你的目录结构是这样的:
你在本地安装了node_js模块vue的话同样可以直接通过script标签引用

浏览器加载ES6模块
浏览器加载 ES6 模块,也使用<script>标签,但是要加入type="module"属性。
<script type="module" src="./foo.js"></script>
浏览器对于带有type="module"的<script>,都是异步加载,不会造成堵塞浏览器,即等到整个页面渲染完,再执行模块脚本,等同于打开了<script>标签的defer属性。
<script type="module" src="./foo.js"></script>
<!-- 等同于 -->
<script type="module" src="./foo.js" defer></script>
ES6 模块也允许内嵌在网页中,语法行为与加载外部脚本完全一致。
<script type="module">
import utils from "./utils.js"; // other code
</script>
参考资料:http://es6.ruanyifeng.com/#docs/module
知识点【JavaScript模块化】的更多相关文章
- 实现一个JavaScript模块化加载器
对任何程序,都存在一个规模的问题,起初我们使用函数来组织不同的模块,但是随着应用规模的不断变大,简单的重构函数并不能顺利的解决问题.尤其对JavaScript程序而言,模块化有助于解决我们在前端开发中 ...
- Javascript模块化编程(三):require.js的用法
Javascript模块化编程(三):require.js的用法 原文地址:http://www.ruanyifeng.com/blog/2012/11/require_js.html 作者: 阮一峰 ...
- Javascript模块化编程(二):AMD规范
Javascript模块化编程(二):AMD规范 作者: 阮一峰 原文地址:http://www.ruanyifeng.com/blog/2012/10/asynchronous_module_d ...
- Javascript模块化编程(一):模块的写法
Javascript模块化编程(一):模块的写法 作者: 阮一峰 原文链接:http://www.ruanyifeng.com/blog/2012/10/javascript_module.html ...
- Javascript模块化编程(二):AMD规范(转)
这个系列的第一部分介绍了Javascript模块的基本写法,今天介绍如何规范地使用模块. (接上文) 七.模块的规范 先想一想,为什么模块很重要? 因为有了模块,我们就可以更方便地使用别人的代码,想要 ...
- Javascript模块化编程(一):模块的写法(转)
随着网站逐渐变成"互联网应用程序",嵌入网页的Javascript代码越来越庞大,越来越复杂. 网页越来越像桌面程序,需要一个团队分工协作.进度管理.单元测试等等......开发者 ...
- Javascript模块化规范
Javascript模块化规范 一.前端js模块化由来与演变 CommonJS 原来叫 ServerJS,推出 Modules/1.0 规范后,在 Node.js 等环境下取得了很不错的实践.09年下 ...
- Javascript模块化开发,使用模块化脚本加载工具RequireJS,提高你代码的速度和质量。
随着前端JavaScript代码越来越重,如何组织JavaScript代码变得非常重要,好的组织方式,可以让别人和自己很好的理解代码,也便于维护和测试.模块化是一种非常好的代码组织方式,本文试着对Ja ...
- Javascript 模块化开发上线解决方案
最近又换部门了,好频繁地说...于是把这段时间搞的小工具们简单整理了一下,作了一个小的总结.这次用一个简单业务demo来向大家介绍一下Javascript模块化开发的方式和自动化合并压缩的一些自己的处 ...
随机推荐
- 树莓派学习笔记(5):成功实现NAS家庭服务器(流媒体播放、文件共享及下载机)
转载请注明:@小五义http://www.cnblogs.com/xiaowuyiQQ群:64770604 一.家庭服务器实现的主要功能 1.流媒体播放服务:利用DLNA实现电视.手机.电脑播放其上面 ...
- js 自己项目中几种打开或弹出页面的方法
自己项目中,几种打开或弹出页面的方法(部分需要特定环境下) var blnTop = false;//是否在顶层显示 ///动态生成模态窗体(通过字符串生成) ///strModalId:模态窗体ID ...
- 20155235 《网络攻防》 实验八 Web基础
20155235 <网络攻防> 实验八 Web基础 实验内容 Web前端HTML(0.5分) 能正常安装.启停Apache.理解HTML,理解表单,理解GET与POST方法,编写一个含有表 ...
- 20155301 Web基础
20155301 Web基础 1.基础问题回答 (1)什么是表单 答: 表单是一个包含表单元素的区域. 表单元素是允许用户在表单中(比如:文本域.下拉列表.单选框.复选框等等)输入信息的元素 (2)浏 ...
- 20155304《网络对抗》Exp7 网络欺诈技术防范
20155304<网络对抗>Exp7 网络欺诈技术防范 实践内容 本实践的目标理解常用网络欺诈背后的原理,以提高防范意识,并提出具体防范方法.具体实践有 (1)简单应用SET工具建立冒名网 ...
- LoRa---她的简介和她的专业术语
LoRa是LPWAN(低功耗广域网)通信技术的一种,其作用距离超过 15 公里,连接节点可达 100 万个.低功耗与长距离极限的组合可将最大数据速率提升至每秒 50千比特(Kbps). LoRa 是 ...
- python 回溯法 子集树模板 系列 —— 19、野人与传教士问题
问题 在河的左岸有N个传教士.N个野人和一条船,传教士们想用这条船把所有人都运过河去,但有以下条件限制: (1)修道士和野人都会划船,但船每次最多只能运M个人: (2)在任何岸边以及船上,野人数目都不 ...
- sql——sql中的各种连接
现有两张表 tablea 和 tableb 各种连接 1.笛尔卡积 SELECT * FROM TabA a,TabB b where a.id = b.id /*笛尔卡积乘积*/ 返回的结果 ...
- 6.Xilinx RapidIO核仿真与包时序分析
转自https://www.cnblogs.com/liujinggang/p/10123498.html 一.软件平台与硬件平台 软件平台: 操作系统:Windows 8.1 64-bit 开发套件 ...
- 洛咕 P3756 [CQOI2017]老C的方块
四染色,贼好想 一个弃疗图形刚好对应一个红-绿-黄-粉色路线(不要吐槽颜色) 就是裸的最小割,建图傻逼懒得写了 #include<bits/stdc++.h> #define il inl ...