ES6语法之export、export defalut、import的用法

4 篇文章 0 订阅
3 篇文章 0 订阅

前景

在 ES6 之前,社区制定了一些模块加载方案,最主要的有 CommonJS 和 AMD 两种。前者用于服务器,后者用于浏览器。ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代现有的 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
ES6 模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。

介绍

关于模块

ES6 模块不是对象,是通过export命令显式指定输出的代码,再通过import命令输入。
一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。

命令

模块功能主要由两个命令构成:export和import。export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。还有export default表示为模块指定默认输出。

加载方式

ES6 模块属于编译时加载也叫做静态加载,就是 ES6 可以在编译时就完成模块加载,效率要比 CommonJS 模块的加载方式。当然,这也导致了没法引用 ES6 模块本身,因为它不是对象。
引擎处理import语句是在执行之前,所以import语句放在if代码块之中毫无意义,因此会报句法错误,而不是执行时错误。

模块用法

通常是export命令显式指定输出的代码,再通过import命令输入,他们那之间的关系基本可用下张图表示
在这里插入图片描述

export

  • export命令可以输出变量,还可以输出函数或类
  • 通常情况下,export输出的变量就是本来的名字,但是可以使用as关键字重命名。
    function v1(){}
    export {
      v1 as streamV1, // 这里使用as重命名,import就可以使用streamV1获取v1方法
    }
export方式用法
  1. 直接输出【 export 直接对应表达式、函数类】
    export var firstName = 'Michael';
    export function fn(){
    }
  1. 括号统一输出(优先使用这种)【export{}里面接收变量函数和类】
    var firstName = 'Michael';
    function fn(){}
    export {firstName, fn}
  1. export default输出,为模块指定默认输出。
  • 与 export不同的是,一个文件中只有一个export default ,而且export default输出不带括号,他也可以直接输出默认值
    export default function () {
      console.log('foo');
    }
    // 第二种
    function foo() {
      console.log('foo');
    }
    export default foo;
    export default 54; // 直接输出默认值

import

  • import 有提升效果,会提升整个模块到头部首先执行,所以不可放在判断语句表达式中
  • import 会加载执行的模块,多个相同的import只会执行一次
import方式用法

1、import 直接加载模块

import 'react'

2、import {} 加载模块,import命令还可以使用as关键字

import {firstName, lastName, year} from './profile';
import { lastName as surname } from './profile' // 这时候使用的是surname模块

3、import * as fn模块的整体加载

import * as circle from './circle';
console.log('圆面积:' + circle.area(4));

4、import _, { each }同时获取默认方法和其他变量

export 与 import 的复合写法

  • 在一个模块之中,先输入后输出同一个模块,import语句可以与export语句写在一起
export { foo, bar } from 'my_module'; // 先输入foo, bar模块再输出
  • 想要输出默认模块,使用as关键字即可
export { es6 as default } from './someModule';
  • ES7有一个提案,简化先输入后输出的写法,拿掉输出时的大括号。
// 提案的写法
export v from 'mod';

输入输出注意事项

  • export命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系。
// 报错 ,方法不能直接输出需要加个{}
function f() {}
export f;
// 报错, 这是输出值而不是接口
export 1;
// 报错
var m = 1;
export m;
  • export default命令其实只是输出一个叫做default的变量,所以它后面不能跟变量声明语句。【和export是有点相反的】
// 正确
var a = 1;
export default a;

// 错误
export default var a = 1;
  • 命令可以出现在模块的任何位置,只要处于模块顶层就可以。如果处于块级作用域内,就会报错
function foo() {
  export default 'bar' // SyntaxError
}
foo()

深入了解

ES6模块加载的实质

ES6模块加载的机制,与CommonJS模块完全不同。CommonJS模块输出的是一个值的拷贝,而ES6模块输出的是值的引用。简单来说就是ES6模块输出值可以被修改,而CommonJS则不行;就像是CommonJS模块新生成对象完成了深拷贝,而ES6模块则引用值是浅拷贝,关于深拷贝浅拷贝可参考这个文章

ES6模块的运行机制是遇到模块加载命令import时,不会去执行模块,而是只生成一个动态的只读引用。等到真的需要用到时,再到模块里面去取值,换句话说,ES6的输入有点像Unix系统的“符号连接”,原始值变了,import输入的值也会跟着变。因此,ES6模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。

由于ES6输入的模块变量,只是一个“符号连接”,所以这个变量是只读的,对它进行重新赋值会报错。

// lib.js
export let obj = {};

// main.js
import { obj } from './lib';

obj.prop = 123; // OK
obj = {}; // TypeError,重新赋值报错

import() 解决动态加载弊端

import语句会取代 Node 的require方法,但是require是运行时加载模块,import语句则无法取代这种动态加载功能。

有一个提案,建议引入import()函数,完成动态加载。import()类似于 Node 的require方法,区别主要是前者是异步加载,后者是同步加载。

import()函数可以用在任何地方,不仅仅是模块,非模块的脚本也可以使用。它是运行时执行,也就是说,什么时候运行到这一句,也会加载指定的模块。另外,import()函数与所加载的模块没有静态连接关系,这点也是与import语句不相同。

浏览器的模块加载

  • 使用方式
<script type="module" src="foo.js"></script> 
// type属性设为module告知浏览器这是一个模块
  • 浏览器对于带有type="module"的

跨模块常量

其实就是相当于申明了一个全局变量

// constants.js
export const A = 1;
export const B = 3;
// 使用
import {A, B} from './constants';
console.log(A); // 1

模块遵守严格模式

ES6 的模块自动采用严格模式,不管你有没有在模块头部加上"use strict",通用限制如下

  • 变量必须声明后再使用
  • 函数的参数不能有同名属性,否则报错
  • 不能使用with语句
  • 不能对只读属性赋值,否则报错
  • 不能使用前缀0表示八进制数,否则报错
  • 不能删除不可删除的属性,否则报错
  • 不能删除变量delete prop,会报错,只能删除属性delete global[prop]
  • eval不会在它的外层作用域引入变量
  • eval和arguments不能被重新赋值
  • arguments不会自动反映函数参数的变化
  • 不能使用arguments.callee
  • 不能使用arguments.caller
  • 禁止this指向全局对象
  • 不能使用fn.caller和fn.arguments获取函数调用的堆栈
  • 增加了保留字(比如protected、static和interface)

参考

http://caibaojian.com/es6/module.html

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值