Es6 中 export和import详解

来源:互联网 发布:最优化方法陈宝林pdf 编辑:程序博客网 时间:2024/05/31 18:38

模块功能主要由两个命令构成:exportimportexport命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。

一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。下面是一个 JS 文件,里面使用export命令输出变量。

// profile.jsexport var firstName = 'Michael';export var lastName = 'Jackson';export var year = 1958;

上面代码是profile.js文件,保存了用户信息。ES6 将其视为一个模块,里面用export命令对外部输出了三个变量。

export的写法,除了像上面这样,还有另外一种。

// profile.jsvar firstName = 'Michael';var lastName = 'Jackson';var year = 1958;export {firstName, lastName, year};

上面代码在export命令后面,使用大括号指定所要输出的一组变量。它与前一种写法(直接放置在var语句前)是等价的,但是应该优先考虑使用这种写法。因为这样就可以在脚本尾部,一眼看清楚输出了哪些变量。

export命令除了输出变量,还可以输出函数或类(class)。

export function multiply(x, y) {  return x * y;};

上面代码对外输出一个函数multiply

通常情况下,export输出的变量就是本来的名字,但是可以使用as关键字重命名。

function v1() { ... }function v2() { ... }export {  v1 as streamV1,  v2 as streamV2,  v2 as streamLatestVersion};

上面代码使用as关键字,重命名了函数v1v2的对外接口。重命名后,v2可以用不同的名字输出两次。

需要特别注意的是,export命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系。

// 报错export 1;// 报错var m = 1;export m;

上面两种写法都会报错,因为没有提供对外的接口。第一种写法直接输出1,第二种写法通过变量m,还是直接输出1。1只是一个值,不是接口。正确的写法是下面这样。

// 写法一export var m = 1;// 写法二var m = 1;export {m};// 写法三var n = 1;export {n as m};

上面三种写法都是正确的,规定了对外的接口m。其他脚本可以通过这个接口,取到值1。它们的实质是,在接口名与模块内部变量之间,建立了一一对应的关系。

同样的,functionclass的输出,也必须遵守这样的写法。

// 报错function f() {}export f;// 正确export function f() {};// 正确function f() {}export {f};

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

export var foo = 'bar';setTimeout(() => foo = 'baz', 500);

上面代码输出变量foo,值为bar,500毫秒之后变成baz

这一点与 CommonJS 规范完全不同。CommonJS 模块输出的是值的缓存,不存在动态更新,详见下文《ES6模块加载的实质》一节。

最后,export命令可以出现在模块的任何位置,只要处于模块顶层就可以。如果处于块级作用域内,就会报错,下一节的import命令也是如此。这是因为处于条件代码块之中,就没法做静态优化了,违背了ES6模块的设计初衷。

function foo() {  export default 'bar' // SyntaxError}foo()

上面代码中,export语句放在函数之中,结果报错。

import 命令

使用export命令定义了模块的对外接口以后,其他 JS 文件就可以通过import命令加载这个模块。

// main.jsimport {firstName, lastName, year} from './profile';function setName(element) {  element.textContent = firstName + ' ' + lastName;}

上面代码的import命令,用于加载profile.js文件,并从中输入变量。import命令接受一对大括号,里面指定要从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块(profile.js)对外接口的名称相同。

如果想为输入的变量重新取一个名字,import命令要使用as关键字,将输入的变量重命名。

import { lastName as surname } from './profile';

import后面的from指定模块文件的位置,可以是相对路径,也可以是绝对路径,.js路径可以省略。如果只是模块名,不带有路径,那么必须有配置文件,告诉 JavaScript 引擎该模块的位置。

import {myMethod} from 'util';

上面代码中,util是模块文件名,由于不带有路径,必须通过配置,告诉引擎怎么取到这个模块。

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

foo();import { foo } from 'my_module';

上面的代码不会报错,因为import的执行早于foo的调用。这种行为的本质是,import命令是编译阶段执行的,在代码运行之前。

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

// 报错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';}

上面三种写法都会报错,因为它们用到了表达式、变量和if结构。在静态分析阶段,这些语法都是没法得到值的。

最后,import语句会执行所加载的模块,因此可以有下面的写法。

import 'lodash';

上面代码仅仅执行lodash模块,但是不输入任何值。

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

import 'lodash';import 'lodash';

上面代码加载了两次lodash,但是只会执行一次。

import { foo } from 'my_module';import { bar } from 'my_module';// 等同于import { foo, bar } from 'my_module';

上面代码中,虽然foobar在两个语句中加载,但是它们对应的是同一个my_module实例。也就是说,import语句是 Singleton 模式。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 简历邮件发错了怎么办 发了简历不回复怎么办 发了简历没回复怎么办 发了简历邮件没有回复怎么办 快手绑定的手机号不用了怎么办 绑定银行卡的手机号不用了怎么办 oppo账号密码忘了怎么办 魅族账号密码忘了怎么办 苹果手机账号密码忘了怎么办 oppo手机账号密码忘了怎么办 华为手机账号密码忘了怎么办 vivo手机账号密码忘了怎么办 金立s9密码忘了怎么办 手机密号忘了怎么办 qq号忘了账号怎么办 推特密码忘了怎么办 沃邮箱改密码短信延迟怎么办 被qq好友拉黑了怎么办 网易邮箱字体变小了怎么办 邮箱注册不了全拼怎么办 家用电器接入两相火线后怎么办 手机充电板坏了怎么办 闪电宝商户乱跳怎么办 网易邮箱发错了怎么办 苹果手机邮件无法连接服务器怎么办 好记星平板电脑开不了机怎么办 邮箱里的文件过期了怎么办 小米手机邮件发不了怎么办 有人加我qq邮箱怎么办 文件太大发邮件太慢怎么办 爱又米发信息怎么办 手机上电子邮件己停止运行怎么办 苹果电子邮件密码忘了怎么办 玩游戏时电脑烫怎么办 qq邮箱独立密码忘记了怎么办 qq邮箱中转站容量不足怎么办 qq邮箱忘记密码了怎么办 qq邮箱超大附件过期怎么办 忘记qq邮箱独立密码怎么办 网易邮箱账号忘了怎么办 微信登录密码忘了怎么办