历史上,JavaScript一直没有模块体系,没法将一个大程序拆分红相互依赖的小文件,再用简单的方法拼装起来。这对开发大型的、复杂的项目造成了巨大的障碍。react
在es6以前社区制定了一些模块加载方案, 主要有 COmmonJS 和 AMD 两种。前者用于服务器,后者用于浏览器。es6
CommonJS 和 AMD 模块 , 采用的是 “运行时加载” , 是将暴露的变量、方法等构成一个对象,而后再从这个而对象上读取对应的方法。也就是说会将全部的方法都进行加载。浏览器
ES6模块 ,采用的是 “编译时加载”或者静态加载。即只加载须要的方法,其余的方法不加载。缓存
ES6能够在编译时就完成模块加载,效率要比CommonJS高,固然,这也致使了无法引用 ES6 模块自己,由于它不是对象。服务器
ES6 的模块自动采用严格模式,无论你有没有在模块头部加上 "use strict"函数
严格模式主要有如下限制 :this
模块功能主要有两个命令构成 : export 和 import 。 export命令用于规定模块的对外接口,import命令用于输入其余模块提供的功能。spa
一个模块就是一个独立的文件。该文件内部的全部变量,外部没法获取。若是你但愿外部可以读取模块内部的某个变量,就必须使用export关键字输出该变量。code
export 命令输出变量 :对象
// 1.
export const fristName = "buzhanhua";
//2.
const lastName = "Jone";
export {lastName}
复制代码
两种写法是等价的,可是推荐第二种,因为export规定的是对外接口因此第二种要使用 {} 而不能直接名称
export 命令输出变量或类(class)。
export function fn(){
console.log("zzz")
}
function fn(){
console.log("zzz")
}
export {fn}
复制代码
一般状况下 , export输出的变量名称就是之后引入时的名称 , 可是可使用 as 关键字重命名。
function fn(){
console.log("zzz")
}
export {
fn as haha,
fn as zzzz
}
复制代码
通过重命名后同一个方法能够以不一样的名称屡次输出。
export语句输出的接口,与对应的值是动态绑定的,即经过该接口,能够取到模块内部实时的值。
export var foo = 'bar';
setTimeout(() => foo = 'baz', 500);
复制代码
上面代码 foo 在500 毫秒后变为 ‘baz’ , 也就是500毫秒后再取则是baz.
这一点与CommonJS规范彻底不一样。CommonJS模块输出的是值的缓存,不存在动态更新
export 命令能够出如今模块的任何位置,只要是模块顶层就能够。
function fn(){
console.log("zzz");
export {lastName}
}
// 报错
复制代码
使用export命令定义了模块的对外接口之后,其余 JS 文件就能够经过import命令加载这个模块。
import命令接受一对大括号,里面指定要从其余模块导入的变量名。大括号里面的变量名,必须与被导入模块(profile.js)对外接口的名称相同。
import {fristName,lastName,haha} from './profile';
复制代码
import 命令可使用 as 关键字,将输入的变量重命名。
import {fristName as bigName} from './profile';
复制代码
import 后面的from 指定文件的位置 , 能够是相对路径, 也能够是绝对路径,.js 能够省略。若是只是模块名,不带有路径,那么必须有配置文件告诉JavaScript该模块的位置。
import 命令具备提高效果,会提高到整个模块的头部,首先执行。
haha();
import {haha} from './profile';
复制代码
上面代码不会报错, 本质是由于, import命令是编译阶段执行的, 在代码运行前。
因为 import 是静态执行的, 因此不能使用表达式和变量 ,这些只有在运行时才能获得结果的语法结构。
import {'ha'+'ha'} from './profile';
let a = 'haha';
import {a} from './profile';
// if 语句 function 都会报错
复制代码
import 语句能够执行所加载的模块 , 但不会输出任何值。
import './profile';
复制代码
若是屡次重复执行同一句import语句,那么只会执行一次,而不会执行屡次。
import { foo } from 'my_module';
import { bar } from 'my_module';
// 等同于
import { foo, bar } from 'my_module';
复制代码
上面代码中,虽然foo和bar在两个语句中加载,可是它们对应的是同一个my_module实例。也就是说,import语句是 Singleton 模式。
除了指定输出某个值,和能够总体输出 , 即便用 "*" 指定一个对象, 全部的输出值都放到这个对象上。
// circle.js
export function sum(a,b){
console.log(a+b);
}
export function area(radius){
let area = Math.PI*radius*radius;
console.log(area);
}
export var a = 12;
//main.js
import * as haha from './circle';
haha.sum(1,2);
haha.area(4);
console.log(haha.a)
复制代码
使用import命令的时候,用户须要知道所要加载的变量名或函数名,不然没法加载。为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。export default在一个模块(文件)中只能使用一次,而export则可使用屡次。
export default function(){
console.log("我是默认")
}
复制代码
其余模块加载该模块时,import命令能够为该匿名函数指定任意名字。
import fn from './circle';
fn() // 我是默认
复制代码
注意 : 这时import命令后面,不使用大括号。
export default命令用在非匿名函数前,也是能够的。
//1.
export default function foo(){
console.log("我是默认")
}
//2.
function foo(){
console.log("我是默认")
}
export default foo
复制代码
上面代码中,foo函数的函数名foo,在模块外部是无效的。加载的时候,视同匿名函数加载。
var a = 1;
export default a; // 正确
export default 1 ; // 正确
export default var a = 1 ; // 错误
复制代码
由于export default命令其实只是输出一个叫作default的变量,因此它后面不能跟变量声明语句。上面代码中,export default a的含义是将变量a的值赋给变量default。因此,最后一种写法会报错。
export default class love {
getLoverName(){
console.log('sun')
}
}
复制代码
若是想在一条import语句中,同时输入默认方法和其余变量,能够写成下面这样
import react , {Component} from 'react';
复制代码
若是在一个模块之中,先输入,后输出同一个模块,import语句能够与export语句写在一块儿
// profile.js
export {sum,area} from './circle';
//等同于
import {sum,area} from './circle';
export {sum,area};
//main.js
import {sum} from './profile';// 就可使用了
复制代码
块的接口更名 (as)
export {area as pipixia} from './circle'
复制代码
总体输出 (*)
export * from './circle';
复制代码
获取某个模块的默认接口,并做为本身的默认接口导出
export {default} from './circle'
复制代码
具名接口改成本身的默认接口
export {sum as default} from './circle';
复制代码
将引入的默认接口转化为本身的具名接口并输出
export {default as hei} from './circle'
复制代码
模块之间也是能够继承的
export * from 'circle';
export var e = 2.71828182846;
export default function(x) {
return Math.exp(x);
}
复制代码
注意,export *命令会忽略circle模块的default方法。而后,上面代码又输出了自定义的e变量和默认方法。
<script type="module" src="foo.js"></script>
复制代码
“循环加载”(circular dependency)指的是,a脚本的执行依赖b脚本,而b脚本的执行又依赖a脚本。
1、export default
2、