CommonJs/ES6/AMD模块的用法以及区别
github地址:
一直以来对CommonJs/AMD/CMD/ES6的文件模块加载一直懵懵懂懂。甚至有时会将CommonJs的exports和ES6的export.default搞混。趁着学习webpack,先搞懂这些模块加载方式再说!!!
随着前端的发展,我们日常开发的功能越来越复杂,文件越来越多。随后前端社区衍生出了CommonJs/AMD/CMD/ES6的几种模块加载方式。
模块加载方式
01: CommonJs
参考地址:阮一峰老师讲解的CommonJs规范
每个文件都是一个单独的模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。
CommonJS
规范规定,每个模块内部,module
变量代表当前模块。这个变量是一个对象,它的exports
属性(即module.exports
)是对外的接口。加载某个模块,其实是加载该模块的module.exports
属性。
CommonJs的特点
- 所有的代码都运行在模块作用域,不会污染全局作用域;
- 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行的结果就会被缓存了,以后再加载就直接读取缓存结果。要想让模块继续运行,必须清空缓存;
- 模块加载顺序,按照其在代码中出现的顺序;
- CommonJs加载模块是同步的;
Module对象
我们在demo01中创建两个js文件,名为c1.js
,main.js
c1.js
每个模块内部都有一个module
对象,代表当前模块。它有以下属性:
module.id
模块的识别符,通常是带有绝对路径的模块文件名。module.filename
模块的文件名,带有绝对路径。module.loaded
返回一个布尔值,表示模块是否已经完成加载。module.parent
返回一个对象,表示调用该模块的模块。module.children
返回一个数组,表示该模块要用到的其他模块。module.exports
表示模块对外输出的值。
console.log(module);
在命令行中执行
node c1.js
输出结果为
Module {
id: '.',
exports: {},
parent: null,
filename: '/Users/Desktop/demo01/c1.js',
loaded: false,
children: [],
paths:
[] }
其中主要关注的是module.exports
这个属性,它表示当前模块对外输出的接口,其他文件加载该模块,实际上就是读取module.exports变量。
注意:一下都在node环境中执行,也就是使用命令行node xxx.js
来执行的因为CommonJs是在node环境中运行的。
创建一个c2.js
文件
c2.js
创建一个对象c2
,通过module.exports
把该对象暴露,在main.js
中,使用require
进行接收。
let c2 = {
num: 5,
sum: function(a,b){
return a+ b
},
person: {
name: 'wbin',
age: '25'
}
}
module.exports = c2;
main.js
let c2 = require('./c2');
console.log(c2); // { num: 5,sum: [Function: sum],person: { name: 'wbin', age: '25' } }
如果要暴露具体内容
创建c3.js
c3.js
let c3 = {
num: 5,
sum: function(a,b){
return a+ b
},
person: {
name: 'wbin',
age: '25'
}
}
module.exports.num = c3.num;
module.exports.person = c3.person;
main.js
let {num, person} = require('./c3');
console.log(num, person); // 5 { name: 'wbin', age: '25' }
在c3.js
中,我暴露出c3
对象的两个属性,num
和person
,在main.js
中使用了ES6的对象扩展来接收对应的值。
module.exports
和exports
(这点只需要了解即可,在开发过程中,建议使用module.exports
)
为了方便,Node
为每个模块提供一个exports
变量,指向module.exports
。这等同在每个模块头部,有一行这样的命令
var exports = module.exports;
但是需要注意的是,不能直接将exports
变量指向一个值,这种行为相当于切断了exports
和module.exports
的关系
在demo01中创建c4.js
c4.js
let c4 = {
num: 5,
sum: function(a,b){
return a+ b
},
person: {
name: 'wbin',
age: '25'
}
}
exports = c4;
main.js
let c4 = require('./c4');
console.log(c4); // {}
以上输出结果是无效的,是一个空对象。
正确的写法是
c4.js
let c4 = {
num: 5,
sum: function(a,b){
return a+ b
},
person: {
name: 'wbin',
age: '25'
}
}
exports.c4 = c4;
为了防止这种不必要的错误,建议使用module.exports
02: ES6
参考地址:《ES6入门》第22和23章
ES6模块的设计是尽可能的静态化,使得编辑时就能确定模块之间的依赖关系,以及输入和输出变量。而CommonJs和AMD则是在运行时才能实现以上结果。
例如CommonJs模块就是一个对象,输入时必须查找对象属性,而ES6模块则可以暴露出任何变量、函数等。
所以说ES6模块的加载方式是“编译时“加载或者是静态加载。
ES6模块功能主要由两个命令构成:export和import。export用来规定模块的对外接口,import用来输入其他模块提供的功能。
demo02e1.js
可以使用export暴露变量
var firstName = 'w';
var lastName = 'bin';
var year = 1993;
export {firstName, lastName ,year};
也可以暴露fun
export function mul(a, b){
return a * b;
}
一般情况下,export输出的变量就是本来的名字,但是可以使用as进行重命名。进行重命名之后我们可以给某个变量(可能是fun)这些进行多次输出。
function add(a, b){
return a + b;
}
function reduce(a, b){
return a - b;
}
export {
add as sum,
reduce as mius,
reduce as jian
}
需要注意的是:ES6模块的import/export
目前不支持在node环境中直接使用,可以使用webpack打包之后在浏览器中查看效果
使用import来加载某个模块
e2.js
export let name = 'wbin';
export let age = 26;
main.js
import {name, age} from './e2';
console.log(name, age);
import命令接收一个大括号{},里面指定要从其他模块加载的变量名。需要注意的是加载的变量名必须和export输出的变量名一致。但是我们可以在improt中给该名称重新命名。
import {name as wbin, age} from './e2';
console.log(wbin, age);
有时我们需要整体加载所需要的模块,可以使用*号来加载
circle.js
export function area(radius) {
return (Math.PI * radius * radius);
}
export function circumference(radius){
return 2 * Math.PI * radius;
}
main.js
// 整体引入
import * as circle from './circle';
console.log(circle.area(2),circle.circumference(2));
默认输出 export default
e3.js
export default function(){
return '123'
}
main.js
import name from './e3';
console.log(name()); // 123
注意:使用默认输出时,import不使用{},使用正常输出时,import需要使用{}!!!
03: AMD
AMD是"Asynchronous Module Definition"的缩写,意思就是"异步模块定义"。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。
AMD也采用require()语句加载模块,它要求两个参数:
require([module], callback);
在demo03文件夹中创建几个文件 index.html,main.js,sum.js,all.js以及简单的webpack配置 webpack.config.js
webpack.config.js
module.exports = {
entry: {
bundle: './main.js'
},
output: {
filename: '[name].js'
},
mode: 'development'
}
sum.js
define(function(){
return {
sum: function(a, b){
return a + b;
}
}
})
main.js
require(['./sum'],function(sum){
console.log(sum.sum(1,2));
})
CommonJs/ES6/AMD模块的用法以及区别的更多相关文章
- 前端模块化之CommonJS,ES6,AMD,CMD
最近在搞跨平台解决方案,讨论关于模块划分的问题以及如何尽量多的复用逻辑代码.于是就有了此文章,之前的博客也写过,不过由于主机商跑路,宝贵的资源也就没了,说多了都是泪~ 这里按模块化发展的历史回溯的时间 ...
- commonJS、AMD和CMD之间的区别
JS中的模块规范(CommonJS,AMD,CMD),如果你听过js模块化这个东西,那么你就应该听过或CommonJS或AMD甚至是CMD这些规范咯,我也听过,但之前也真的是听听而已. 现在就看看吧, ...
- CommonJS、AMD、CMD和ES6模块化区别
本文参考自:https://www.cnblogs.com/chenguangliang/p/5856701.html 1.CommonJS NodeJS是CommonJS规范的实现,webpack ...
- 模块化-CommonJs、AMD、CMD、ES6
在了解AMD,CMD规范前,还是需要先来简单地了解下什么是模块化,模块化开发?模块化是指在解决某一个复杂问题或者一系列的杂糅问题时,依照一种分类的思维把问题进行系统性的分解以之处理.模块化是一种处理复 ...
- ECMA Script 6_模块加载方案 ES6 Module 模块语法_import_export
1. 模块加载方案 commonJS 背景: 历史上,JavaScript 一直没有模块(module)体系, 无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来. 其他语言都有这项功能: ...
- js模块化编程之CommonJS和AMD/CMD
js模块化编程commonjs.AMD/CMD与ES6模块规范 一.CommonJS commonjs的require是运行时同步加载,es6的import是静态分析,是在编译时而不是在代码运行时.C ...
- 模块化(CommonJs、AMD、CMD、UMD)发展历史与优缺点
全文主要整理自摘自<Webpack中文指南>(好文,建议直接去看,以下仅对该系列文章中的<历史发展>篇幅进行备份——也整理了点其他内容) 模块化 模块化是老生常谈了,这里不做阐 ...
- 对于模块加载:ES6、CommonJS、AMD、CMD的区别
运行和编译的概念 编译包括编译和链接两步. 编译,把源代码翻译成机器能识别的代码或者某个中间状态的语言. 比如java只有JVM识别的字节码,C#中只有CLR能识别的MSIL.还简单的作一些比如检查有 ...
- JavaScript模块化CommonJS/AMD/CMD/UMD/ES6Module的区别
目录 JS-模块化进程 原始的开发方式 CommonJS && node.js AMD && Require.js CMD && Sea.js UMD ...
随机推荐
- Java——static关键字---18.09.27
static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但在Java语言中没有全局变量的概念. static关键字主要有两种作用: 一.为某特定数据类 ...
- ajax同步和异步的切换
ajax为网页提供了非常不错的异步机制,但是有时候两个ajax放在一起,希望第一个完成后再继续第二个ajax的执行.这时候可以将第一个ajax代码带上同步参数即可,如下: $.ajax({ async ...
- 蓝牙技术(BlueTooth)——(一)
一,概述 蓝牙是一种短距离的无线通信技术标准. 蓝牙协议分为4层,即核心协议层,电缆替代协议层,电话控制协议层,和 采纳的其它协议层. 这4中协议中最重要的是核心协议.蓝牙的核心协议包括基带 ...
- Django调试models输出的SQL语句
django1.3在shell下,调试models变得更为简单了,不用像之前的版本,手工去调用django query,才能打印出之前的代码是执行的什么SQL语句. 1.3开始只需在settings. ...
- stm8编程tips(stvd)
编译完成时显示程序占用的flash和ram大小 将附件压缩包中的mapinfo.exe解压到stvd的安装路径\stvd中 在工程上点右键选settings 右侧的选项卡选择Linker,将categ ...
- JS控制文本框输入的内容
总而言之: 先在‘<input>’ 里输入 onkeyup="value=value.replace(/[^\X]/g,'')" 然后在(/[\X]/g, ...
- javascript数据相关处理,序列化反序列化,数据编码与解码
对象序列化简而言之,将对象转为字符串.在数据的传输过程中,经常会使用到对象序列化. javascript中常用的对象序列化:JSON.stringify(); javascript中常用的对象反序列化 ...
- android中的文件(图片)上传
android中的文件(图片)上传其实没什么复杂的,主要是对 multipart/form-data 协议要有所了解. 关于 multipart/form-data 协议,在 RFC文档中有详细的描述 ...
- 让webapi支持CORS,可以跨域访问
1.在NuGet里搜索webapi找到下面的扩展,添加进项目里. 2.在Global.asax中添加一行代码 protected void Application_Start() { //添加CORS ...
- fiddler抓包工具的基本使用
fiddler是基于C#的HTTP抓包工具. fiddler的原理: fiddler是http代理服务器,它会抓取浏览器向服务器发送的HTTP请求,然后在将该请求发送到服务器.再获取从服务器返回的请求 ...