zoukankan      html  css  js  c++  java
  • es6 Module

    前言:

      这是阮一峰老师的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 1;
    
    // 报错
    var m = 1;
    export m;

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

    // 写法一:这种我不理解
    export var m = 1;
    
    // 写法二:输出一个对象,这个对象有一个 m 属性,m属性与m变量,一一对应
    var m = 1;
    export {m};
    
    // 写法三:输出一个n,n与m一一对应
    var n = 1;
    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 = 1;
    
    // 正确
    var a = 1;
    export default a;
    
    // 错误
    export default var a = 1;

      同时想要两种输出

    import _, { each } from 'lodash';

    八、es6模块加载的实质

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

      问题1:

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

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

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

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

     

  • 相关阅读:
    wf(三)
    WF(二)
    WF4.0入门(一)
    枚举
    函数和立即函数
    对象字面量
    Break和continue语句
    对象
    循环语句
    条件分支语句(SWICH语句)
  • 原文地址:https://www.cnblogs.com/miaowwwww/p/6280463.html
Copyright © 2011-2022 走看看