模块功能主要由两个命令构成:export和import。export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。
一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。
//a.js文件
export var name = '张帅';
export var age = 18;
export var sex = '男';
var name = '张帅';
var age = 18;
var sex = '男';
var obj = {
fullName: '张三',
age:20,
sex:'男'
}
export {name, age, sex, obj};
推荐使用第二种写法,方便在代码结尾查看所输出变量;
export function plusHandle (a,b){
return a+b;
}
//b.js
function plusHandle(a,b){
return a+b;
}
function minusHandle(a,b){
return a-b;
}
export{ plusHandle, minusHandle };
//a.js
var name = '张帅';
function plusHandle(a,b){
return a+b;
}
export {name as name2, name as fullName, plusHandleas plus};
as关键字可重命名输出变量的名字,name可以用不同的名字输出两次。
export命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系
export 1; //正确写法 export var m=1;
var m =1; //正确写法var m=1; export {m} export {m as n};
export m;
目前,export 命令能够对外输出的就是三种接口:函数(Functions), 类(Classes),var、let、const 声明的变量(Variables)。
export语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值。
export var foo = 'bar';
setTimeout(() => foo = 'baz', 500);
输出变量foo,值为bar,500 毫秒之后变成baz。取到的值也会实时更新为baz;
这一点与 CommonJS 规范完全不同。CommonJS 模块输出的是值的缓存,不存在动态更新;
export命令可以出现在模块的任何位置,只要处于模块顶层就可以。如果处于块级作用域内,就会报错;import亦然;
//报错语法
function foo() {
export default 'bar' // SyntaxError
}
foo()
使用export命令定义了模块的对外接口以后,其他 JS 文件就可以通过import命令加载这个模块。
import后面的from指定模块文件的位置,可以是相对路径,也可以是绝对路径
//main.js
//加载变量
import {name, age, sex} from './a.js';
//加载方法
import {plusHandle, minusHandle} from './b.js';
import {name as name2} from './a.js';
import命令输入的变量都是只读的,因为它的本质是输入接口。也就是说,不允许在加载模块的脚本里面,改写接口。
//报错
import {name} from './a.js'
name = '王军';// Syntax Error : 'name ' is read-only;
//引入变量为对象,则不会报错,这种写法很难查错,建议输入变量仅保持只读
import {obj} from './a.js';
obj.name = '李四';
import命令具有提升效果,会提升到整个模块的头部,首先执行;
//正常写法
import {plusHandle} from './b.js';
plusHandle();
//颠倒写法,先使用,后引入
//不会报错,import会被提升到整个模块头部,首先执行
plusHandle();
import {plusHandle} from './b.js';
// 报错
import { 'f' + 'oo' } from 'my_module';
// 报错
let module = 'my_module';
import { foo } from module;
// 报错
if (x === 1) {
import { foo } from 'module1';
} else {
import { foo } from 'module2';
}
由于import是静态执行,所以不能使用表达式和变量,这些只有在运行时才能得到结果的语法结构。
//import {plusHandle, minusHandle} from './b.js';
//整体加载
import * as b from './b.js';
b.plusHandle(3,5);
b.minusHandle(18,2);
export输出时,import输入时需要知道输出的变量名或函数名,否则无法加载;
export default可实现快速加载模块,用户自定义输入名称;
// export-default.js
export default function() {
console.log('foo');
}
import可为输出函数任意指定名字,需注意,此时import后面无需使用大括号
// import-default.js
import customName from './export-default';
customName(); // 'foo'
// export-default.js
export default function foo() {
console.log('foo');
}
// 或者写成
function foo() {
console.log('foo');
}
export default foo;
import foo from './export-default';
foo(); // 'foo'
//写法二
import aa from './export-default';
aa(); // 'foo'
本质上,export default就是输出一个叫做default的变量或方法,然后系统允许你为它取任意名字;
// modules.js
function add(x, y) {
return x * y;
}
export {add as default};
// 等同于
// export default add;
// app.js
import { default as foo } from 'modules';
// 等同于
// import foo from 'modules';
正是因为export default命令其实只是输出一个叫做default的变量,所以它后面不能跟变量声明语句。
// 正确
export var a = 1;
// 正确
var a = 1;
export default a; //等价于 export {a as default}
// 错误
export default var a = 1;
上面代码中,export default a的含义是将变量a的值赋给变量default。所以,最后一种写法会报错。
同样地,因为export default命令的本质是将后面的值,赋给default变量,所以可以直接将一个值写在export default之后。
// 正确
export default 42;
// 报错
export 42;
浏览器加载 ES6 模块,也使用script标签,但是要加入type="module"属性
//ceshi.js
export const a = 1;
export const b = 2;
export function addHandle(a,b){
return a+b;
}
//index.html 引入ceshi.js
<script type="module">
import {a,b,addHandle} from './js/ceshi.js'
console.log('模块引入变量',a,b);
console.log('模块引入函数',addHandle(2,5));
</script>
公共页面常见写法
//a.js; export default写法
let a=1;
let b=2;
let c = function(a,b){
return a+b;
}
function d(a,b){
return a-b;
}
export default {
a,b,c,d
};
//上面写法等价于下面b.js; export写法
//b.js
export const obj = {
a: 1,
b: 2,
c: function(a,b){
return a+b;
}
d: function(a,b){
return a-b;
}
}
//公共页面引入
//如uni中在main.js中引入
import a from '@/common/js/a.js'
Vue.prototype.$a = a//赋值到vue里面
//写法二引入
import {b} from '@/common/js/b.js';
Vue.prototype.$b= b;//赋值到vue里面
//使用方法
console.log(this.$a.a);
console.log(this.$b.c(5,8));
单个页面按需引入常见写法
//b.js
export const obj={
name:'张三',
age:18
};
export const a=1;
export const b=2;
export function c(a,b){
return a+b;
}
export function d(a,b){
return a-b;
}
//单页面中引入,按需引入
import { c, d } from '@/common/js/b.js';
c(1,5);
//ceshi.js
export default{
a:1,
b:2,
}
export function getDate(num){
num = num ? num : 0;
const currentTime = new Date().getTime() - num * 24 * 60 * 60 * 1000;
const date = new Date(currentTime);
let year = date.getFullYear();
let month = date.getMonth() + 1;
let day = date.getDate();
month = month > 9 ? month : '0' + month;
day = day > 9 ? day : '0' + day;
return `${year}-${month}-${day} 00:00:00`;
}
import mod from '@/common/js/api.js'; //mod可任意命名
import {getDate} from '@/common/js/api.js'; //getDate必须与export导出变量名一致
console.log('mod',mod);//mod {a: 1, b: 2}
console.log('getDate',getDate());//getDate 2023-11-06 00:00:00
注:export default一个文件只能出现一个
ES6 模块与 CommonJS 模块完全不同。它们有三个重大差异:
//CommonJS a.js
var a=1;
var b = 2;
function sum(a,b){
return a+b;
}
module.exports={
a: a,
b: b,
sum: sum
}
//其他页面引入使用
var mod = require('@/common/js/a.js');
console.log(mod.a);//1
console.log(sum(2,5));//7
阮一峰文档参考