• 模块加载


    概述

    今天恰好看了有关模块加载的文章,挺有意思的,以前虽然在写react博客的时候用到了模块加载,但只是粗浅的认识而已,所以今天大致的查阅了一番,总结了一下,记录下来供以后开发时参考,相信对其他人也有用。

    参考了ES6 In Depth: ModulesECMAScript 6 入门

    浏览器并没有实现

    虽然浏览器支持了es6的大部分内容,但是很遗憾,大多数浏览器还并不支持es6的模块加载语法,通过在浏览器的开发者工具查看并没有module对象,也没有import或export方法:

    //开发者工具的控制台输入
    module //ReferenceError
    export //ReferenceError
    import //ReferenceError
    

    并且,babel只默认转换新的js语法,而不转换新的API。也就是说,如果要进行模块加载的话,只能借用一些库或者打包工具比如webpack了。

    值得一提的是,阮一峰的es6入门里面提到可以用type=module的方法来进行模块加载,但是我在chrome浏览器试了没有成功,mdn也说浏览器并不支持模块加载。(根据stackflow的说法,只有Chrome 61, Firefox 54,MS Edge 16和Safari 10.1支持模块加载。)

    module基础

    关于es6的模块加载有以下2点需要注意:

    • 在模块里面即使不写use strict,它也会自动变成严格模式。
    • 并没有module关键字,但是需要使用import和export关键字,并且这些关键字能出现在顶层作用域的任何地方。
    //kittydar.js
    export {detectCats, Kittydar};
    
    function detectCats(canvas, options) { ... }
    class Kittydar { ... }
    
    //main.js
    import {detectCats, Kittydar} from "kittydar.js";
    

    当然,也可以在import或export的时候重命名

    import {flip as flipOmelet} from "eggs.js";
    import {flip as flipHouse} from "real-estate.js";
    
    export {
      v1 as streamV1,
      v2 as streamV2,
      v2 as streamLatestVersion
    };
    

    上面的写法,import的方法都需要和export的方法名字相同,这非常不方便。我们希望默认export一个方法,然后import就可以任意写方法名,写法如下:

    let myObject = {
      field1: value1,
      field2: value2
    };
    export {myObject as default};
    
    //另一种写法
    export default {
      field1: value1,
      field2: value2
    };
    

    es6也支持把目标文件的所有export的方法导入到一个对象里面:

    import * as cows from "cows";
    //使用的时候通过cows.moo()调用。
    

    如果在一个模块中,先导入然后导出同一个模块,可以像这样简化写:

    export { foo, bar } from 'my_module';
    
    // 可以简单理解为
    import { foo, bar } from 'my_module';
    export { foo, bar };
    

    模块加载的机制

    es6并定义模块加载的细节,它把这些留给浏览器自己来实现。它只要求以下四件事:

    1. 解析:浏览器模块源码并检查语法错误。
    2. 加载:浏览器加载所有import的模块。(至于怎么加载,并没有标准)
    3. 链接:import的模块并不是复制,而是引用。
    4. 运行:运用模块中的代码。

    静态与动态

    js是一门动态的语言,但是模块加载却是静态的,主要表现在以下几个方面:

    • 只能在顶层作用域而不能在函数作用域中使用import或export。
    • 并不支持循环加载。
    • Module是冻结的,你不能在加载的时候引入新的方法。
    • 模块加载的时候需要按顺序加载,并不能懒加载或者按需加载。
    • 只要一个import的模块报错,整个程序都不能运行。
    • 单个模块加载前后没有钩子,不能进行控制。

    与以前的模块加载的比较

    以前的模块加载技术主要是CommonJS和AMD风格,他们都是用require方法,但是却有着本质的不同,主要表现在:

    • CommonJS风格常用于服务器,号称“运行时加载”,它是同步加载的,在浏览器运行的话,会发生很严重的阻塞。另外它的原理是深复制整个模块对象。
    • AMD风格常用于浏览器,号称“编译时加载”,在编译时就完成模块加载,所以效率比CommonJS高,它并不加载整个对象,而是加载选用的几个方法,所以可以按需加载。
  • 相关阅读:
    IBinder在进程之间传递一个对象的形式(一)
    Xaml在string(串)定义常量和处理空间
    c 有意思的数组初始化
    C 文件直接包含
    [面试技巧]16个经典面试问题回答思路
    centos6安装bt工具transmission
    clearcase 中一些概念和操作
    C/C++ Resources
    Linux I/O 重定向详解及应用实例
    c/c++ 直接使用动态库 dlopen
  • 原文地址:https://www.cnblogs.com/yangzhou33/p/8870833.html
Copyright © 2020-2023  润新知