1、概述
①、特点:
-
ES6新增的特性,类似于java中import
-
有两个关键字:export-》导出,import-》导入
-
区分更明细,可以只导出一个变量、对象或者函数,而java只能引入整个类
②、和java比较
-
js中没有Java里用来定义成员的访问权限的public、private等修饰符,所以用export做部分变量导出,二者孰优孰劣见仁见智
-
js模块引入的优点
-
导入即可用,无需再去关注原生文件其它属性、方法、对象、变量、函数的访问权限
-
2、使用方式汇总
1、export 基本导入
使用说明
-
在变量、函数声明处添加export关键字
-
要导出的变量或函数必须有修饰符
-
export var a = 1; (√)
-
export a; (错)
-
函数同理,需function修饰
-
原因见《2.3 export default特点》第一项
-
-
不可以直接导出常量
-
import {要导入的对象集合} from '文件路径';
-
注意:被导入的变量、函数必须用大括号包裹,否则报错
-
可选择导入,支持导入部分变量、函数
代码示例
export var a =1; export let b = 2; export const c = 3; export var d; d = 4; let name = 'showMyName'; export function showMyName(){ ('我是一个要被导出的函数-->'+name); }
import {a,b,c,d,showMyName} from './'; (a); (b); (c); (d); showMyName(); 输出结果: 1 2 3 4 我是一个要被导出的函数-->showMyName
2、export Default 模块化
使用说明
-
使用export defualt导出
-
相比于export每次只能导出一个变量或函数,export可以导出一个集合,也就是所谓的module
-
import时不需要加上大括号,并且可自定义导入模块的名字
-
也就是说,import a from '' 等同于 import b from '';
-
自定义模块名,使得代码的可读性更高,但也会导致规范化问题,可能本人看着顺眼,另一个人就不喜欢了
-
-
可以直接导出常量
代码示例
var a =1; var b =2; function logA(){ ('a的值为--->'+a); } export default {a,logA};
import impModule from './'; (); (()); 执行结果: 1 a的值为--->1
特点--自动将模块包装成对象导出
①、直接导出常量
原因分析(不一定对,以后再分析):
-
导入模块时,相当于导入了一个对象!
-
那么自定义的模块名,就成为了模块对象的变量名
-
对象就灵活起来了,可以有name/age/getName()等属性或方法,也可以本身就代表一个常量值
-
所以defaultModule就相当于一个简单number类型对象,值是99
-
所以可以看到一个现象
-
export defualt 99; (√)
-
export defualt {99,88}; (×) 这种写法在js看来不是想导出两个常量,而是你要导出一个Object对象,没有属性、方法那必 然报错
-
export defualt [99,88]; (√) 将两个常量包装成一个数组对象即可
-
-
代码示例
;
export default 99;
;
import defaultModule from './'; (defaultModule); 执行结果: 99
②、导出多个变量
var a =1; var b =2; function logA(){ ('a的值为--->'+a); } export default {a,logA};
import impModule from './'; (impModule); 执行结果: {a:1,logA: [Function: logA] }
明显看到导入的module内容被自动包括成了一个对象
3、组合导出
使用说明
-
在一个js中,只可以有一个export default
-
但是,可以有0或多个export
-
特性和前面两种方式一样,只不是是组合使用,方便了
代码示例
export var a = 1; let b = 2; function logB() { (b); } export default {b,logB};
import {a} from './'; import impDefault from './'; (a); (); () 执行结果: 1 2 2
3、常见问题
①、export、import会导致变量提升吗?
答:
-
import、export可能只需要用代码执行顺序来形容更合适
-
export不会出现变量提升的现象,甚至会在最后执行,能不能变量提升主要是看 变量本身的定义修饰符(var、let、const、function)
//错误写法1: a = 1; export let a; //正确写法1 a = 1; export var a; //正确写法2 export let a; a = 1;
原因分析(猜测):
//错误写法1在js解释器中的样子 a = 1; let a; export a;//伪代码,关注顺序即可,这种写法本身是错误的 //正确写法1在js解释器中的样子 var a; a = 1; export a; //正确写法2在js解释器中的样子 let a; a = 1; export a;
现象:export语句总在所有代码之后执行
-
import会出现类似变量提升的现象,原因是import语句会被解释器提升到所有代码之前执行
//下列两种写法均可执行 import {a} from './'; (a); 或者: (a); import {a} from './'; 结果: 1
现象:import语句总在所有代码之前执行
和java的区别:java的import语句显式写在文件的最上方,js允许import写在任何地方,但看起来结果都是import语句总在所有代码之前执行
②、export default也会在代码在代码最下面执行吗?
答:
-
和export不同,export default不会在代码最下方执行
-
它就在代码所在行导出模块对象
-
先导出后定义,分两种情况,会不会报错全看变量本身的修饰符有没有变量提升的现象
export default a; var a = 1; //导出的实际是个{undefined},就是代码执行顺序 //解释器中如下 var a; export default a; a = 1;
export default a; let a = 1; //直接报错 ReferenceError: Cannot access 'a' before initialization(初始化之前不能访问a,因为这会儿a还没被定义)
③、导入模块后修改了变量值,会导致原模块中的值改变吗?
答:
不清楚原理,只通过现象总结一下,以后明白了再补充:
-
import的简单类型不可直接修改,原因不清楚,不知道js是咋处理的
export function logA() { (a); } export let a = 1;
import {a,logA} from './'; (a); a = 2; (a); logA() /* 代码执行到 a=2 时会直接报错!! TypeError: Assignment to constant variable. 就好像a成了一个被const修饰的变量一样 */
-
引用类型修改会影响原来值
export function logA() { (a); } export let a = {name:'张三'};
import {a,logA} from './'; (a); = "李四"; (a); logA() //执行结果 { name: '张三' } { name: '李四' } { name: '李四' }
④、export如何导出常量
答:
-
无法直接导出常量 export a; 直接报错
-
曲线救国 export {a}; 就可以了
-
export default 可能就是把这个过程给隐式的执行了一下,谁知道呢