美文网首页
ES6 模块的导入导出笔记

ES6 模块的导入导出笔记

作者: 冬瓜不削皮 | 来源:发表于2018-10-27 20:34 被阅读0次

ES6 支持 javascript 模块化,模块之间的导入导出有一定的规则,因为总是记不住,做一下学习笔记。

export 导出

export 命令用于规定对外的接口。一个模块就是一个独立的文件,文件内部的变量,外部是无法获取的,如果想读取模块内部的某个变量,必须使用 export 关键字输出该变量。

export 语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值。

export 命令可以出现在模块的任何位置,只要处于模块顶层就可以。如果处于块级作用域内,就会报错,也就是不能出现在表达式,if 判断等块内。

// export 第一个种写法
export var firstName = "zhangsan";

// 第二种写法,输出一组变量时,一定要有大括号
var secondName = "lisi";
var thirdName = "andy";
export {secondName, thirdName};

// 输出函数
function v1(){}
export {v1}

// 也可以更改输出的名字,对外暴露的就是newFn
export {v1 as newFn}

import 命令

  • 独立加载

不允许修改 import 进来的变量,除非操作的是一个变量中的属性,一般情况下不建议修改变量,仅做只读。

import 命令具有提升效果,会提升到整个模块的头部,首先执行。

由于 import 是静态执行,所以不能使用表达式和变量,这些只有在运行时才能得到结果的语法结构。所谓静态执行,指的是在编译时执行,在程序运行时不执行。

如果多次重复执行同一句import语句,那么只会执行一次,而不会执行多次。

// 第一种引入,直接引入输出的,大括号里面的变量名必须与export里面的一一对应
import {firstName,secondName} from './profile.js';

// 第二种写法,改变名称,将lastName 改为 surname
import {lastName as surname} from './profile.js';

// 仅仅执行,不输入。以下仅仅执行lodash模块,但是不输入任何值。
import 'lodash';        
  • 整体加载

整体加载用在不知道导出来的名字,用星号(*)指定一个对象,所有输出值都加载在这个对象上面。

// 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(4));
console.log('圆周长:' + circle.circumference(14));

// 下面两行都是不允许的,因为不允许运行时改变
circle.foo = 'hello';
circle.area = function () {};

export default 默认输出

export default 为模块指定默认输出。模块只能有一个 export default,但是可以有多个 export

// export-default.js
export default function () {
    console.log('foo');
}

//   其他函数在加载时,可以以任意名字来加载
// import-default.js
import customName form './export-default';
customName();    // 'foo'   

// 后面不能跟表达式,因为export default 输出的是一个default变量
export default var a = 1;    // 错误

// 当输出 export default 后,可以同时 import 多个
import _, {each, each as forEach} from 'lodash';

// export default 也可以用来输出类。
// MyClass.js
export default class { ... }

// main.js
import MyClass from 'MyClass';
let o = new MyClass();

export 与 import 的复合写法

export 与 import 的复合写法相当于转手导出,当前模块没有引用导出的模块。

export { foo, bar } from 'my_module';
// foo和bar实际上并没有被导入当前模块,只是相当于对外转发了这两个接口,导致当前模块不能直接使用 foo 和 bar。
// 可以简单理解为
import { foo, bar } from 'my_module';
export { foo, bar };


// 接口改名
export { foo as myFoo } from 'my_module';

// 整体输出
export * from 'my_module';

// 具名接口改为默认接口的写法如下。
export { es6 as default } from './someModule';

// 等同于
import { es6 } from './someModule';
export default es6;

// 同样地,默认接口也可以改名为具名接口。
export { default as es6 } from './someModule';

CommonJS 的写法

CommonJS通过 module 对象来把 javascript 代码模块化。引入模块通过 require语法,导出模块通过 module.exports = {} 。范例

// lib.js
var counter = 3;
function incCounter() {
  counter++;
}
module.exports = {
  counter: counter,
  incCounter: incCounter,
};

// 在main.js里面加载这个模块。
// main.js
var mod = require('./lib');

console.log(mod.counter);  // 3
mod.incCounter();
console.log(mod.counter); // 3
// 上面代码说明,lib.js模块加载以后,它的内部变化就影响不到输出的mod.counter了。这是因为mod.counter是一个原始类型的值,会被缓存。除非写成一个函数,才能得到内部变动后的值。

读取模块内的数值 需要通过取值器函数。

// lib.js
var counter = 3;
function incCounter() {
  counter++;
}
module.exports = {
  get counter() {
    return counter
  },
  incCounter: incCounter,
};
// 上面代码中,输出的counter属性实际上是一个取值器函数。现在再执行main.js,就可以正确读取内部变量counter的变动了。

$ node main.js
3
4

ES6 模块的引用是复制的引用,一处修改,其他地方都会改。

// lib.js
export let counter = 3;
export function incCounter() {
  counter++;
}

// main.js
import { counter, incCounter } from './lib';
console.log(counter); // 3
incCounter();
console.log(counter); // 4

node 中的 import

目前,Node 的import命令只支持加载本地模块(file:协议),不支持加载远程模块。

如果模块名不含路径,那么import命令会去node_modules目录寻找这个模块。

如果模块名包含路径,那么import命令会按照路径去寻找这个名字的脚本文件。范例

import 'file:///etc/config/app.json';
import './foo';
import './foo?search';
import '../bar';
import '/baz';
/* 如果脚本文件省略了后缀名,比如import './foo',Node 会依次尝试四个后缀名:./foo.mjs、./foo.js、./foo.json、./foo.node。如果这些脚本文件都不存在,Node 就会去加载./foo/package.json的main字段指定的脚本。如果./foo/package.json不存在或者没有main字段,那么就会依次加载./foo/index.mjs、./foo/index.js、./foo/index.json、./foo/index.node。如果以上四个文件还是都不存在,就会抛出错误。

最后,Node 的import命令是异步加载,这一点与浏览器的处理方法相同 。

参考链接:http://es6.ruanyifeng.com/#docs/module

相关文章

网友评论

      本文标题:ES6 模块的导入导出笔记

      本文链接:https://www.haomeiwen.com/subject/zozdtqtx.html