前言:

  这是阮一峰老师的ECMA6入门module一章的缩减,只抽取了我在项目中有用到的内容。带着问题去看老师的教程。感觉吸收更快,也明白了偶尔遇到的export不出来的问题。

es6模块设计思想:

  ES6 模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。

es6模块不是对象:

// CommonJS模块
let { stat, exists, readFile } = require('fs'); // 等同于
let _fs = require('fs');
let stat = _fs.stat, exists = _fs.exists, readfile = _fs.readfile;

  上面代码的实质是整体加载fs模块(即加载fs的所有方法),生成一个对象(_fs),然后再从这个对象上面读取3个方法。这种加载称为“运行时加载”,因为只有运行时才能得到这个对象,导致完全没办法在编译时做“静态优化”。

  ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。不会加载整个fs。

// ES6模块
import { stat, exists, readFile } from 'fs';

  由于 ES6 模块是编译时加载,使得静态分析成为可能。

  除了静态加载带来的各种好处,ES6 模块还有以下好处。

  • 不再需要UMD模块格式了,将来服务器和浏览器都会支持 ES6 模块格式。目前,通过各种工具库,其实已经做到了这一点。
  • 将来浏览器的新 API 就能用模块格式提供,不再必须做成全局变量或者navigator对象的属性。
  • 不再需要对象作为命名空间(比如Math对象),未来这些功能可以通过模块提供。

关于es6模块的特性

一、严格模式:

  es6模块默认使用严格模式,不管你有没有使用  'use strict'

二、export

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

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

  这里的意思是不能直接输入一个变量,函数,类

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

  正确的,有一一对应关系的export,函数 function,类 class 也是要遵守这种规则的。

// 写法一:这种我不理解
export var m = ; // 写法二:输出一个对象,这个对象有一个 m 属性,m属性与m变量,一一对应
var m = ;
export {m}; // 写法三:输出一个n,n与m一一对应
var n = ;
export {n as m};
// 报错:输出的 f 就是 函数 f 没有对应关系
function f() {}
export f; // 正确
export function f() {}; // 正确
function f() {}
export {f};

  export的换名输出

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

三、import

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

  注意:import在编译阶段执行,可以理解为跟变量提升,函数提升有一样的特性,但是比这两种提升晚一点执行。

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

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

  import语句会执行所加载的模块,因此可以有下面的写法。只执行一下lodash,但是不输入任何值

import 'lodash';

  只想列出不同的import写法:

// 变量名与export一一对应
import {firstName, lastName, year} from './profile'; // 使用新变量名代替
import { lastName as surname } from './profile';

四、模块的整体加载

  一个模块中可以有多个export,import中可以使用 * 把他们全部收在一个对象中 * as mymodule

import * as circle from './circle';

五、export default 命令

  为模块设置默认输出,在import的时候不需要使用{},也可以随便给一个名字这个默认输出。

// export-default.js
export default function foo() {
console.log('foo');
} // 或者写成
function foo() {
console.log('foo');
}
export default foo; // import
import xxx from 'export-default.js'

  本质上,export default就是输出一个叫做default的变量或方法,然后系统允许你为它取任意名字

// modules.js
function add(x, y) {
return x * y;
}
export {add as default};
// 等同于
// export default add; // app.js
import { default as xxx } from 'modules';
// 等同于
// import xxx from 'modules';

  正是因为export default命令其实只是输出一个叫做default的变量,所以它后面不能跟变量声明语句。(怪不得老是说,找不到模块)

// 正确
export var a = ; // 正确
var a = ;
export default a; // 错误
export default var a = ;

  同时想要两种输出

import _, { each } from 'lodash';

八、es6模块加载的实质

  ES6模块加载的机制,与CommonJS模块完全不同。CommonJS模块输出的是一个值的拷贝(值类型是拷贝,引用类型是引用),而ES6模块输出的是值的引用(值类型,引用类型都是引用)

  问题1:

  commonJS 得到的是一个复制,require后得到的mod.counter,跟lib.js里面的counter已经没有联系,(可以理解为require多少次,复制多少份)

// lib.js
var counter = ;
function incCounter() {
counter++;
}
module.exports = {
counter: counter,
incCounter: incCounter,
}; // main.js
var mod = require('./lib'); console.log(mod.counter); //
mod.incCounter();
console.log(mod.counter); //

  es6模块的优点就是共享一份,因为它输出的仅仅是引用

// lib.js
export let counter = ;
export function incCounter() {
counter++;
} // main.js
import { counter, incCounter } from './lib';
console.log(counter); //
incCounter();
console.log(counter); //

 

es6 Module的更多相关文章

  1. JavaScript ES6 module 模块

    在使用JavaScript开发大型项目时,模块开发概念是一个必须考虑的问题.其目的就是通过命名空间对各类业务对象进行一定的封装,防止命名冲突. 本篇着重介绍ES6 module中的export和imp ...

  2. 在 npm 中使用 ES6 module

    node 从 v8.5.0起 支持了 ES6 module. 只需保存文件名为 .mjs ,并通过一个option 可以开启执行,如 node --experimental-modules index ...

  3. 深入 CommonJs 与 ES6 Module

    目前主流的模块规范 UMD CommonJs es6 module umd 模块(通用模块) (function (global, factory) { typeof exports === 'obj ...

  4. 再次梳理AMD、CMD、CommonJS、ES6 Module的区别

    AMD AMD一开始是CommonJS规范中的一个草案,全称是Asynchronous Module Definition,即异步模块加载机制.后来由该草案的作者以RequireJS实现了AMD规范, ...

  5. 通过ES6 Module看import和require区别

    前言 说到import和require,大家平时开发中一定不少见,尤其是需要前端工程化的项目现在都已经离不开node了,在node环境下这两者都是大量存在的,大体上来说他们都是为了实现JS代码的模块化 ...

  6. 前端模块化IIFE,commonjs,AMD,UMD,ES6 Module规范超详细讲解

    目录 为什么前端需要模块化 什么是模块 是什么IIFE 举个栗子 模块化标准 Commonjs 特征 IIFE中的例子用commonjs实现 AMD和RequireJS 如何定义一个模块 如何在入口文 ...

  7. CommonJS与ES6 Module的使用与区别

    CommonJS与ES6 Module的使用与区别 1. CommonJS 1.1 导出 1.2 导入 2. ES6 Module 2.1 导出 2.2 导入 3. CommonJS 与 ES6 Mo ...

  8. es6 module + webpack

    其实在之前本人就看了 es6 里面的一部分内容,当然是阮一峰大神的 ECMAScript 6 入门. 最近闲来无事又来看下,其中 Module 的语法 这章时候,用里面代码跑的时候,理所当然的报错 S ...

  9. es6+require混合开发,兼容es6 module,import,export

    近一年,一直很忙,做了不少的项目,不过都不是太满意,毕竟是别人的作品,不好意思写出来.最近打算开发一个es6的项目,项目中用到require,本文主要讲解es6的module规范怎么与require的 ...

随机推荐

  1. Java程序员应该知道的10个Eclipse调试技巧

    Eclipse是众多Java程序员实用的开发工具,其中开发技巧也是繁多,但作为优秀的Java程序员,需要掌握最起码的调试技巧. 1 条件断点 2 异常断点 3 监视点 4 评估/检查 5 修改变量值 ...

  2. 使用sqlldr向Oracle导入大的文本(txt)文件

    我们有多种方法可以向Oracle数据库里导入文本文件,但如果导入的文本文件过大,例如5G,10G的文本文件,有些方法就不尽如意了,例如PLSQL Developer中的导入文本功能,如果文本文件过大, ...

  3. 怎样以学习单片机为契机,逐步成为优秀的project师

    现状 不知道阅读本文的读者,在初学单片机时是否和我以前一样迷茫.看到各种新的术语,疑惑不解:不知道从何学起:照着书中的样例一步一步做都没有问题,可是自己试着做东西,遇到各种问题却不会解决,向别人提问, ...

  4. ASP.NET MVC进阶

    ASP.NET MVC进阶 一.ASP.NET MVC中的AJAX应用 首先,在ASP.NET MVC中使用自带的ajax功能,必须要导入2个js文件(顺序不能颠倒): ASP.NET MVC提供了2 ...

  5. mysql支持的数据类型及其测试

    原文:mysql支持的数据类型及其测试 1.基础知识 1.1如何来查看mysql的帮助手册 ?int Help float; 1.2创建表的规则 CREATE TABLE [IF NOT EXISTS ...

  6. c#多线程随记回顾

    C#多线程随记回顾 1.创建多线程方式知道的有三种: ---手动创建Thread.使用线程池.使用task任务 ---手动创建Thread,分两种带参数和不带参数的帮助委托器 eg:  //帮助器委托 ...

  7. Redis简介与简单安装

    Redis简介与简单安装   一.NoSQL的风生水起 1.1 后Web2.0时代的发展要求 随着互联网Web2.0网站的兴起,传统的关系数据库在应付Web2.0网站,特别是超大规模和高并发的SNS类 ...

  8. JavaScript实例技巧精选(9)—计算器实例1

    >>点击这里下载完整html源码<< 这是截图: 利用Javascript和html实现的一个计算器实例,核心代码如下: <script language="J ...

  9. Fiddler工具

    Fiddler初探 我们知道监视Http和Https请求的工具有多种,例如:HttpWatch,FireBug等.但是今天接触到一种新的工具Fiddler.Fiddler能记录所有客户端和服务器的ht ...

  10. 从uibutton的点击谈谈ios的响应事件

    最近在做一个项目,接连遇到两个关于点击事件的问题. 1.点击button不能响应事件的. 2.子view的frame超出了父view的容器大小,也不能响应点击事件. 效果图如右: 1.第一张图中的弹出 ...