export default 和 export 区别:
1.export与export default均可用于导出常量、函数、文件、模块等
2.你可以在其它文件或模块中通过import+(常量 | 函数 | 文件 | 模块)名的方式,将其导入,以便能够对其进行使用
3.在一个文件或模块中,export、import可以有多个,export default仅有一个
4.通过export方式导出,在导入时要加{ },export default则不需要
1.export
//a.js
export const str = "blablabla~";
export function log(sth) {
return sth;
}
对应的导入方式:
//b.js
import { str, log } from 'a'; //也可以分开写两次,导入的时候带花括号
2.export default
//a.js
const str = "blablabla~";
export default str;
对应的导入方式:
//b.js
import str from 'a'; //导入的时候没有花括号
使用export default命令,为模块指定默认输出,这样就不需要知道所要加载模块的变量名
//a.js
let sex = "boy";
export default sex(sex不能加大括号)
//原本直接export sex外部是无法识别的,加上default就可以了.但是一个文件内最多只能有一个export default。
其实此处相当于为sex变量值"boy"起了一个系统默认的变量名default,自然default只能有一个值,所以一个文件内不能有多个export default。
// b.js
本质上,a.js文件的export default输出一个叫做default的变量,然后系统允许你为它取任意名字。所以可以为import的模块起任何变量名,且不需要用大括号包含
import any from "./a.js"
import any12 from "./a.js"
console.log(any,any12) // boy,boy
作者:开车去环游世界
链接:https://www.jianshu.com/p/edaf43e9384f
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
模块基础知识
每一个ES6模块都是一个包含JS代码的文件,模块本质上就是一段脚本,而不是用module
关键字定义一个模块,但是模块与脚本还是有两点区别:
- 在ES6模块中,无论你是否加入“
use strict;
”语句,默认情况下模块都是在严格模式下运行。 - 在模块中你可以使
用import
和export
关键字。
我们先来讨论export
。默认情况下,你在模块中的所有声明相对于模块而言都是寄存在本地的。如果你希望公开在模块中声明的内容,并让其它模块加以使用,你一定要导出这些功能。想要导出模块的功能有很多方法,其中最简单的方式是添加export
关键字。
// kittydar.js - 找到一幅图像中所有猫的位置
// (事实上是Heather Arthur写的这个库)
// (但是她没有使用ES6中新的模块特性,因为那时候是2013年)
export function detectCats(canvas, options) {
var kittydar = new Kittydar(options);
return kittydar.detectCats(canvas);
}
export class Kittydar {
... 处理图片的几种方法 ...
}
// 这个helper函数没有被export。
function resizeCanvas() {
...
}
...
你可以导出
所有的最外层函数
、类
以及var
、let
或const
声明的变量。
了解这些,你就可以编写一个简单的模块。你不需要将所有代码都放在一个IIFE或回调中,你只需要在模块中解放手脚,声明你需要的所有内容。代码就是模块,不是一段脚本,所以所有的声明都被限定在模块的作用域中,对所有脚本和模块全局不可见。你需要做的是将组成模块公共API的声明全部导出。
在模块中,除export之外的代码无异于普通代码,你可以访问类似Object
和Array
这样的全局对象。如果你在web浏览器中运行模块,你甚至可以使用document
对象和XMLHttpRequest
对象。
在一个独立文件中,我们可以导入detectCats()
函数然后用它来做点儿什么:
// demo.js - Kittydar的demo程序
import {detectCats} from "kittydar.js";
function go() {
var canvas = document.getElementById("catpix");
var cats = detectCats(canvas);
drawRectangles(canvas, cats);
}
如果想从一个模块中导入多个名称,你可以这样写:
import {detectCats, Kittydar} from "kittydar.js";
当你运行的模块中包含一条import
声明时,首先会加载被导入的模块;然后依赖图的深度优先遍历按顺序执行每一个模块的主体代码;为了避免形成回环,所有已执行的模块都会被忽略。
这些就是模块的基本知识了,相当简单吧。;-)
Export列表
你不需要标记每一个被导出的特性,你只需要在花括号中按照列表的格式写下你想导出的所有名称:
export {detectCats, Kittydar};
// 此处不需要 `export`关键字
function detectCats(canvas, options) { ... }
class Kittydar { ... }
export
列表可以在模块文件最外层作用域的每一处声明,不一定非要把它放在模块文件的首行。你也可以声明多个export
列表,甚至通过其它的export
声明打造一个混合的export
列表,只要保证每一个被导出的名称是唯一的即可。
重命名import和export
恰恰有时候,导出的名称会与你需要使用的其它名称产生冲突,ES6为你提供了重命名的方法解决这个问题,当你在导入名称时可以这样做:
// suburbia.js
// 这两个模块都会导出以`flip`命名的东西。
// 要同时导入两者,我们至少要将其中一个的名称改掉。
import {flip as flipOmelet} from "eggs.js";
import {flip as flipHouse} from "real-estate.js";
...
同样,当你在导出的时候也可以重命名。你可能会想用两个不同的名称导出相同的值,这样的情况偶尔也会遇到:
// unlicensed_nuclear_accelerator.js - 无DRM(数字版权管理)的媒体流
// (这不是一个真实存在的库,但是或许它应该被做成一个库)
function v1() { ... }
function v2() { ... }
export {
v1 as streamV1,
v2 as streamV2,
v2 as streamLatestVersion
};
Default exports
现在广泛使用的模块系统有CommonJS、AMD两种,设计出来的新标准可以与这两种模块进行交互。所以假设你有一个Node项目,你已经执行了npm install lodash
,你的ES6模块可以从Lodash中导入独立的函数:
import {each, map} from "lodash";
each([3, 2, 1], x => console.log(x));
但是也许你已经习惯看到_.each
的书写方式而不想直接用each
函数呢?或者你就真的想导入整个_
函数呢,毕竟_对于Lodash而言至关重要。
针对这种情况,你可以换用一种稍微不太一样的方法:不用花括号来导入模块。
import _ from "lodash";
这种简略的表达方法等价于import {default as _} from "lodash";
。在ES6的模块中导入的CommonJS模块和AMD模块都有一个默认的
导出,如果你用require()
加载这些模块也会得到相同的结果——exports
对象。
ES6模块不只导出CommonJS模块,它的设计逻辑为你提供导出不同内容的多种方法,默认导出的是你得到的所有内容。举个例子,在用这种写法的时候,据我所知,著名的colors包就没有任何针对ES6的支持。像大多数npm上的包一样,它是诸多CommonJS模块的集合,但是你可以正确地将它导入到你的ES6代码中。
// `var colors = require("colors/safe");`的ES6等效代码
import colors from "colors/safe";
如果你想让自己的ES6模块有一个默认的导出,实现的方法很简单,默认导出与其它类型的导出相似,没有什么技巧可言,唯一的不同之处是它被命名为“default
”。你可以用我们刚才讨论的重命名语法来实现:
let myObject = {
field1: value1,
field2: value2
};
export {myObject as default};
这种简略的表达方法看起来更清爽:
export default {
field1: value1,
field2: value2
};
关键字export default
后可跟随任何值:一个函数、一个类、一个对象字面量,只要你能想到的都可以。
模块对象
很抱歉新特性有点儿多,但JavaScript不是唯一这样做的语言:出于某些原因,每一种语言中的模块系统都有这么一堆又独立又小,虽然无聊但是很方便的特性。不过还好,我们只剩一样东西没讲了。好吧,是两样。
import * as cows from "cows";
当你import *
时,导入的其实是一个模块命名空间对象,模块将它的所有属性都导出了。所以如果“cows”模块导出一个名为moon()
的函数,然后用上面这种方法“cows”将其全部导入后,你就可以这样调用函数了:cows.moo()
。
聚合模块
有时一个程序包中主模块的代码比较多,为了简化这样的代码,可以用一种统一的方式将其它模块中的内容聚合在一起导出,可以通过这种简单的方式将所有所需内容导入再导出:
// world-foods.js - 来自世界各地的好东西
// 导入"sri-lanka"并将它导出的内容的一部分重新导出
export {Tea, Cinnamon} from "sri-lanka";
// 导入"equatorial-guinea"并将它导出的内容的一部分重新导出
export {Coffee, Cocoa} from "equatorial-guinea";
// 导入"singapore"并将它导出的内容全部导出
export * from "singapore";
这些export-from
语句每一个都好比是在一条import-from
语句后伴随着一个export
。与真正的导入内容的方法不同的是,这些导入内容再重新导出的方法不会在作用域中绑定你导入的内容。如果你打算用world-foods.js
中的Tea
来写一些代码,可别用这种方法导入模块,你会发现当前模块作用域中根本找不到Tea
。
如果从“singapore”导出的任何名称碰巧与其它的导出冲突了,可能会触发一个错误,所以使用export *
语句的时候要格外小心。
呼!终于讲完了所有的语法!现在来讲一些有趣的内容。
import实际都做了些什么?
如果我说它什么都没做,你敢信?
哦,看来你没那么容易上当啊。好吧,你相信标准里面通常都不会规定import
的行为么?如果真是这样,那这是件好事儿么?
ES6将模块加载过程的细节完全交由最终的实现来定义,模块执行的其它部分倒是在规范中有详细定义。
粗略地讲,当你通知JS引擎运行一个模块时,它一定会按照以下四个步骤执行下去:
- 语法解析:阅读模块源代码,检查语法错误。
- 加载:递归地加载所有被导入的模块。这也正是没被标准化的部分。
- 连接:每遇到一个新加载的模块,为其创建作用域并将模块内声明的所有绑定填充到该作用域中,其中包括由其它模块导入的内容。
- 如果你的代码中有
import {cake} from "paleo"
这样的语句,而此时“paleo”模块并没有导出任何“cake
”,你就会触发一个错误。这实在是太糟糕了,你都快要运行模块中的代码了,都是cake惹的祸! - 运行时:最终,在每一个新加载的模块体内执行所有语句。此时,导入的过程就已经结束了,所以当执行到达有一行
import
声明的代码的时候……什么都没发生!
看到了嘛?我可告诉过你结果是“啥都没有”哦。事关编程语言我绝不撒谎!