export 与export default区别

1、ES6之前的模块化


JavaScript最初被设计时并不是用来大型应用的,所以在其设计中也并没有模块化标准。随着其应用越来越广泛,一些开源社区和开发者提出了一些模块标准,如:CommoneJS模块化、异步模块定义(AMD)等。这些规范在提出后得到了广泛关注,并逐步被应用到了一些企业级的大型应用。

CommoneJS模块化:该标准最成功的应用是Node.js(Node.js在CommoneJS的基础上就进行了一定的扩展)。其主要特点是语法简洁,模块使用同步加载机制,主要使用在服务器端。

异步模块定义(AMD):该标准的典型应该是RequireJS。其主要特点是模块使用异步加载,主要使用在浏览器端。

2、ES6模块系统


详细信息科参考es6 Module

它具有以下特性:

  • 简洁的语法。语法将比CommoneJS更简单,只使用export和import实现模块的导出和导入
    • 使用export关键字定义导出对象,这个关键字可以无限次使用
    • 使用import关键字引入导入对象,这个关键字可导入任意数量的模块
  • 模块结构可以做静态分析。这使得在编译时就能确定模块的依赖关系,以及输入和输出的变量
  • 模块支持异步加载
  • 为加载模块提供编程支持,可以按需加载
  • 比CommonJS更优秀的循环依赖处理

支持状况

ES6为JavaScript带来了模块机制,但ES6的模块机制在当前所有的浏览器及Node.js中均不受支持。但我们可以通过一些编译器来对ES6语法进行转换,从而利用这些新特性给我们项目带来便利:

Babel-Babel是一个ES6语法转换为ES5语法的转换器,其支持对ES6模块语法的转换,包括:异步加载、状态隔离、顶级命名空间隔离等
es6-module-transpiler -将ES6模块编译为AMD规范或者CommonJS规范的模块
ES6 module loader-能支持动态加载ES6风格的模块
Traceur-Google开发的JS转换编译器,目的在于支持更多的JavaScript特性包括ES6模块

导出对象
在现有的模块系统中,每个JavaScript代码文件在ES6中都是一个模块。只有模块中的对象需要被外部调用时,模块才会输出对象,其余则都是模块的私有对象。该处理方式将细节进行封装,仅导出必要的功能。

内联导出
ES6模块里的对象可在创建它们的声明中导出。一个模块中可无数次使用export,所有的对象将被一起导出。请看下面的例子:

export class Employee{
  constructor(id, name, dob){
    this.id = id;
    this.name=name;
    this.dob= dob;
  }
  getAge(){
    return (new Date()).getYear() - this.dob.getYear();
  }
}
export function getEmployee(id, name, dob){
  return new Employee(id, name, dob);
}
var emp = new Employee(1, "Rina", new Date(1987, 1, 22));

案例中的模块导出了两个对象: Employee类,getEmployee函数。因对象emp未被导出,所以其仍为模块私有。

导出一组对象
尽管内联导出很有效,但在大规模模块中,它就很难发挥作用了,因为我们可能无法追踪到模块导出来的对象。在这种情况下,更好的办法是,在模块的末尾单独进行导出声明,以导出该模块中的全部对象。

class Employee{
  constructor(id, name, dob){
    this.id = id;
    this.name=name;
    this.dob= dob;
  }
  getAge(){
    return (new Date()).getYear() - this.dob.getYear();
  }
}
function getEmployee(id, name, dob){
  return new Employee(id, name, dob);
}
var x = new Employee(1, "Rina", new Date(1987, 1, 22));
export {Employee, getEmployee};

在导出时,重命名对象也是可以的。如下例所示,Employee在导出时名字改为了Associate,函数GetEmployee改名为getAssociate。

export {
    Associate as Employee,
    getAssociate as getEmployee
  };

Default导出
使用关键字default,可将对象标注为default对象导出。default关键字在每一个模块中只能使用一次。而默认导出每个导出只有一个单一值,这个输出可以是一个函数、类或其它类型的值

export default function() {}; // 可以导出一个函数
export default class(){}; // 也可以出一个类
const D = 123;

export default D; 
export { D as default };       //与上面的等价

导入模块

现有模块可以使用关键字import导入到其它模块。一个模块可以被导入任意数量的模块中。下文展示了导入模块的不同方式。

如果模块包含一些逻辑要执行,且不会导出任何对象,此类对象也可以被导入到另一模块中。如下面案例所示:

import './module1.js';

导入默认对象

采用Default导出方式导出对象,该对象在import声明中将直接被分配给某个引用,如下例中的“d”。

import d from './module1.js';
import { default as d } from './module1.js';  //等价于上面

导入命名的对象

正如以上讨论的,一个模块可以导出许多命名对象。如果另一模块想导入这些命名对象,需要在导入声明中一一列出这些对象。举个例子:

import {Employee, getEmployee} from './module1.js';

当然也可在同一个声明中导入默认对象和命名对象。这种情况下,默认对象必须定义一个别名,如下例。

 import {default as d, Employee} from './module1.js';

导入所有对象

以上几种情况,只有import声明中列举的对象才会被导入并被使用,而其它对象则无法在导入模块中使用。当然,这就要求用户了解哪些对象可以导出并加以利用。如果模块导出大量对象,另一模块想引入所有导出的对象,就必须使用如下声明:

import * as allFromModule1 from './module1.js';

allFromModule1这一别名将指向所有从module1导出的对象。在导入模块中,它们作为属性可被访问。

可编程式的按需导入

如果想基于某些条件或等某个事件发生后再加载需要的模块,可通过使用加载模块的可编程API(programmatic API)来实现。使用System.import方法,可按程序设定加载模块。这是一个异步的方法,并返回Promise。

System.import('./module1.js')
    .then(function(module1){
        //use module1
    }, function(e){
        //handle error
    });

猜你喜欢

转载自blog.csdn.net/xingaichenai/article/details/55667394