美文网首页
js中的模块

js中的模块

作者: 张培_ | 来源:发表于2018-06-18 21:16 被阅读23次

    模块概念

    • 模块可以被理解成一个包含了js代码的一个文件,也可以被理解成一个命名空间
    • 模块之间互相独立,也可以互相引用。
    • 模块内的内容默认状态下都是private,但也可以通过暴露方式,将其转换成public,被其他模块访问

    为什么要有模块?

    • 防止全局变量被污染,无法保证不与其他模块发生变量名冲突
    • 可以提高代码的复用率

    模块规范有哪些?

    在es6以前,js并没有关于模块的官方规范没有模块体系(连css都有@import),因此社区制定了一些非官方的模块功能: CommonJS、AMD

    CommonJS

    Node.js的模块规范(运行时加载)

    • 在CommonJS中,每一个模块都会有一个module对象。使用module.exports和exports暴露模块
    • 在CommonJS中,有一个全局性方法require(),用于加载模块

    CommonJS模块规范中的注意点

    • CommonJS规范加载模块是同步

    • CommonJS中每个模块是一个对象这个对象的名字就是该文件的名字

      • 因此每次加载都必须将整个模块都加载进来
    • CommonJS模块的加载机制是,输入的是被输出的值的拷贝。也就是说,一旦输出一个值,模块内部的变化就影响不到这个值

      //a.js
      
      let a = 3
      
      module.exports = a
      
      a = 5
      
      
      //b.js
      
      const a = require('./a.js')
      console.log(a) // 是3而不是5
      
    • 执行时机是运行时,只能在运行时确定模块之间的依赖关系,而不能进行静态优化,因此require可以直接用作动态引用。

    AMD(异步模块定义)

    为浏览器环境设计,因为 CommonJS 模块系统是同步加载的(简单的总结,就是让你可以使用回调)

    • 产生背景:
      • 有了服务器端模块以后,很自然地,大家就想要客户端模块。而且最好两者能够兼容,一个模块不用修改,在服务器和浏览器都可以运行
      • 但是CommonJS 模块系统是同步加载的,这对服务器端不是一个问题,因为所有的模块都存放在本地硬盘,可以同步加载完成,等待时间就是硬盘的读取时间。但是,对于浏览器,这却是一个大问题,因为模块都放在服务器端,等待时间取决于网速的快慢,可能要等很长时间,浏览器处于"假死"状态

    由于现在有了ES6模块规范,因此不多介绍AMD了

    ES6模块规范

    ES6 在语言标准的层面上,实现的模块功能,旨在成为浏览器和服务器通用的模块解决方案(显然nodejs还在沿用CommonJS方案)。编译时加载

    • 模块功能主要由两个命令构成:export和import
      • 还包含export default,但只是export的语法糖

        //a.js
        const a = 5
        const b = 8
        export a;
        export default b;
        //等价于 export { b as default}
        
        //b.js
        import b from 'a.js'
        
        //等价于 import {b as default} from 'a.js'
        
        import {a} from 'a.js'
        

    ES6模块规范中的注意点

    • ES6 在编译时就能确定模块的依赖关系.
      • import命令会被 JavaScript 引擎静态分析,在编译时就引入模块代码,而不是在代码运行时加载,所以无法实现条件加载。也正因为这个,使得静态分析成为可能。
    • ES6模块不是对象
      • 因此通过export 命令显式指定输出的代码,而不是将某部分代码放入模块对象中
      • 在import时可以指定加载某个输出值,而不是加载整个模块
    • ES6模块加载(import)的是输出(export)的引用,指代的是同一个对象
      • 因此export之后再次修改被export的值,import到的是修改后的值,因为是同一个引用

    CommonJs和ES6模块对比

    • 对于模块的加载时机不同

      • CommonJS运行时加载
      • ES6编译时加载

      例子:

      if(//条件){
      import react from 'react'
      }
      
      if(//条件){
        export const a = 3;
      }
      
      //以上两种情况都会报错
      //'import' and 'export' may only appear at the top level
      
      if(//条件){
          const React = require('react');
      }
      
      if(//条件){
        const a = 3;
        module.exports a;
      }
      
      //以上两种情况都不会报错
      
      • 当你把es6的import或者export放在某个block中会出现这样的报错'import' and 'export' may only appear at the top level.

      A module's structurebeing static means that you can determine imports and exports at compile time (statically) – you only have to look at the source code, you don’t have to execute it. 链接

      • 使用require和module.exports是运行时因此不会报错
    • 模块类型不同

      • ES6不是对象
      • CommonJS是一个module对象

      例子:

      const React = require('react');
      const Component = React.Component;
      // commonJs必须将整个模块对象引入,然后使用`.`找出模块中的属性
      
      import { Component } from 'react';
      //但是es6可以指定加载某个输出值
      
      
    • 加载的模块和暴露的模块之间关系

      • CommonJS:加载的模块是暴露的模块的拷贝
      • ES6:加载的模块是暴露的模块的引用,指代同一个对象
    • import/export 比 module.exports/require 用法更多样一些

    动态引用: require和import()区别

    • require同步的加载,返回加载回来的module
    • import()函数返回的是一个 Promise

    相关文章

      网友评论

          本文标题:js中的模块

          本文链接:https://www.haomeiwen.com/subject/qnlijftx.html