当前位置: 首页 > news >正文

ES6 module(模块化)

前言

历史上,JavaScript一直没有模块体系,无法将一个大程序拆分成相互依赖的小文件,再用简单的方法拼装起来。这对开发大型的、复杂的项目形成了巨大的障碍。

在es6之前社区制定了一些模块加载方案, 主要有 COmmonJS 和 AMD 两种。前者用于服务器,后者用于浏览器。

ES6 module 和 CommonJS 及 AMD 的比较

CommonJS 和 AMD 模块 , 采用的是 “运行时加载” , 是将暴露的变量、方法等构成一个对象,然后再从这个而对象上读取对应的方法。也就是说会将所有的方法都进行加载。

ES6模块 ,采用的是 “编译时加载”或者静态加载。即只加载需要的方法,其他的方法不加载。

ES6可以在编译时就完成模块加载,效率要比CommonJS高,当然,这也导致了没法引用 ES6 模块本身,因为它不是对象。

严格模式

ES6 的模块自动采用严格模式,不管你有没有在模块头部加上 "use strict"

严格模式主要有以下限制 :

  • 变量必须声明后再使用
  • 函数参数不能有同名属性,否则报错
  • 不能使用with 语句
  • 不能对只读属性赋值,否则报错
  • 不能使用 arguments.callee
  • 不能使用 arguments.calles
  • 禁止this 指向全局对象
  • 不能使用前缀0表示八进制数,否则报错
  • 不能删除变量delete prop,会报错,只能删除属性delete global[prop]
  • eval不会在它的外层作用域引入变量
  • eval和arguments不能被重新赋值
  • arguments不会自动反映函数参数的变化

export 指令

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

一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。

  1. export 命令输出变量 :

      // 1.
      export const fristName = "buzhanhua";
      //2.
      const lastName = "Jone";
      export {lastName}
    复制代码

两种写法是等价的,但是推荐第二种,由于export规定的是对外接口所以第二种要使用 {} 而不能直接名称

  1. export 命令输出变量或类(class)。

      export function fn(){
              console.log("zzz")
      }
      
      function fn(){
               console.log("zzz")
        }
      export {fn}
    复制代码
  2. 通常情况下 , export输出的变量名称就是以后引入时的名称 , 但是可以使用 as 关键字重命名。

      function fn(){
           console.log("zzz")
      }
      export {
           fn as haha,
           fn as zzzz
      }
    复制代码

经过重命名后同一个方法可以以不同的名称多次输出。

  1. export语句输出的接口,与对应的值是动态绑定的,即通过该接口,可以取到模块内部实时的值。

       export var foo = 'bar';
       setTimeout(() => foo = 'baz', 500);
    复制代码

上面代码 foo 在500 毫秒后变为 ‘baz’ , 也就是500毫秒后再取则是baz.

这一点与CommonJS规范完全不同。CommonJS模块输出的是值的缓存,不存在动态更新

  1. export 命令可以出现在模块的任何位置,只要是模块顶层就可以。

      function fn(){
              console.log("zzz");
              export {lastName}
      }
      // 报错
    复制代码

import 命令

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

  1. import命令接受一对大括号,里面指定要从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块(profile.js)对外接口的名称相同。

      import {fristName,lastName,haha} from './profile';
    复制代码
  2. import 命令可以使用 as 关键字,将输入的变量重命名。

      import {fristName as bigName} from './profile';
    复制代码
  3. import 后面的from 指定文件的位置 , 可以是相对路径, 也可以是绝对路径,.js 可以省略。如果只是模块名,不带有路径,那么必须有配置文件告诉JavaScript该模块的位置。

  4. import 命令具有提升效果,会提升到整个模块的头部,首先执行。

       haha();
       import {haha} from './profile';
    复制代码

上面代码不会报错, 本质是因为, import命令是编译阶段执行的, 在代码运行前。

  1. 由于 import 是静态执行的, 所以不能使用表达式和变量 ,这些只有在运行时才能得到结果的语法结构。

        import {'ha'+'ha'} from './profile';
        
        let a = 'haha';
        import {a} from './profile';
        // if 语句 function 都会报错
    复制代码
  2. import 语句可以执行所加载的模块 , 但不会输出任何值。

      import './profile';
    复制代码
  3. 如果多次重复执行同一句import语句,那么只会执行一次,而不会执行多次。

      import { foo } from 'my_module';
      import { bar } from 'my_module';
      // 等同于
      import { foo, bar } from 'my_module';
    复制代码

上面代码中,虽然foo和bar在两个语句中加载,但是它们对应的是同一个my_module实例。也就是说,import语句是 Singleton 模式。

模块的整体加载

除了指定输出某个值,和可以整体输出 , 即使用 "*" 指定一个对象, 所有的输出值都放到这个对象上。

     // circle.js
     export function sum(a,b){
               console.log(a+b);
     }

     export function area(radius){
             let area = Math.PI*radius*radius;
             console.log(area);
     }

     export var a = 12;
     
     //main.js
     import * as haha from './circle';
     
      haha.sum(1,2);
      haha.area(4);
      console.log(haha.a)
复制代码

export default 命令

使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载。为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。export default在一个模块(文件)中只能使用一次,而export则可以使用多次。

      export default function(){
               console.log("我是默认")
      }
复制代码

其他模块加载该模块时,import命令可以为该匿名函数指定任意名字。

     import fn from './circle';
     fn() // 我是默认
复制代码

注意 : 这时import命令后面,不使用大括号。

export default命令用在非匿名函数前,也是可以的。

      //1.
      export default function foo(){
                  console.log("我是默认")
      }
     //2.
     function foo(){
                  console.log("我是默认")
     }
     export default foo
复制代码

上面代码中,foo函数的函数名foo,在模块外部是无效的。加载的时候,视同匿名函数加载。

export default输出变量

     var a = 1;
     export default a; // 正确
     
     export default 1 ; // 正确
     
     export default var a = 1 ; // 错误
复制代码

因为export default命令其实只是输出一个叫做default的变量,所以它后面不能跟变量声明语句。上面代码中,export default a的含义是将变量a的值赋给变量default。所以,最后一种写法会报错。

export default输出类

     export default class love {
          getLoverName(){
                console.log('sun')
      }
     
     }
复制代码

如果想在一条import语句中,同时输入默认方法和其他变量,可以写成下面这样

     import react , {Component} from 'react';
复制代码

export 与 import 的复合写法

如果在一个模块之中,先输入,后输出同一个模块,import语句可以与export语句写在一起

     // profile.js
     export {sum,area} from './circle';
     
     //等同于
     import {sum,area} from './circle';
     export {sum,area};
     
     //main.js
     
     import {sum} from './profile';// 就可以使用了
复制代码
  1. 块的接口改名 (as)

      export {area as pipixia} from './circle'
    复制代码
  2. 整体输出 (*)

      export * from './circle';
    复制代码
  3. 获取某个模块的默认接口,并作为自己的默认接口导出

      export {default} from './circle'
    复制代码
  4. 具名接口改为自己的默认接口

      export {sum as default} from './circle';
    复制代码
  5. 将引入的默认接口转化为自己的具名接口并输出

      export {default as hei} from './circle'
    复制代码

模块的继承

模块之间也是可以继承的

      export * from 'circle';
      export var e = 2.71828182846;
      export default function(x) {
            return Math.exp(x);
     }
复制代码

注意,export *命令会忽略circle模块的default方法。然后,上面代码又输出了自定义的e变量和默认方法。

浏览器的模块加载

     <script type="module" src="foo.js"></script>
复制代码

循环加载

“循环加载”(circular dependency)指的是,a脚本的执行依赖b脚本,而b脚本的执行又依赖a脚本。

总结

一、export default

  1. export default 向外暴露成员,可以使用任意变量来接收。
  2. 在一个模块中,export default只允许使用一次。
  3. 在一个模块中可以同时使用export default 和 export

二、

  1. 使用export暴露的成员,只能使用{}的形式接收,这种方式叫做按需引入。
  2. export可以向外暴露多个成员,需要哪个用哪个即可,不需要都用。
  3. 使用export导出的成员时,名称必须一致。
  4. 若是非得改名则可以使用as 关键字改名

相关文章:

  • jquery.editable-select带输入框的下拉框
  • Docker login失败问题的处理
  • Apache+Tomcat负载均衡
  • Kubernetes系统架构与组件功能
  • python 字符串方法
  • MMKV源码学习
  • Zookeeper简介
  • 微服务架构,你必须要知道的一些事儿!
  • 自动化测试|录制回放效果差异检测
  • JAVA springcloud ssm b2b2c多用户商城系统源码(一)构建第一个SpringBoot工程
  • Selenium-Switch--切换浏览器tab/iframe/alart
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • JavaScript中in操作符(for..in)、Object.keys()和Object.getOwnPropertyNames()的区别
  • Day01:总结一下str的常见操作吧~
  • Bytom储蓄分红合约解析
  • CoolViewPager:即刻刷新,自定义边缘效果颜色,双向自动循环,内置垂直切换效果,想要的都在这里...
  • css的样式优先级
  • Fastjson的基本使用方法大全
  • Java 最常见的 200+ 面试题:面试必备
  • Rancher-k8s加速安装文档
  • Redis中的lru算法实现
  • VirtualBox 安装过程中出现 Running VMs found 错误的解决过程
  • 闭包,sync使用细节
  • 翻译:Hystrix - How To Use
  • 翻译--Thinking in React
  • 分布式事物理论与实践
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 关键词挖掘技术哪家强(一)基于node.js技术开发一个关键字查询工具
  • 每个JavaScript开发人员应阅读的书【1】 - JavaScript: The Good Parts
  • 消息队列系列二(IOT中消息队列的应用)
  • 小程序01:wepy框架整合iview webapp UI
  • 移动互联网+智能运营体系搭建=你家有金矿啊!
  • 走向全栈之MongoDB的使用
  • mysql面试题分组并合并列
  • 带你开发类似Pokemon Go的AR游戏
  • #vue3 实现前端下载excel文件模板功能
  • (11)MATLAB PCA+SVM 人脸识别
  • (C++)八皇后问题
  • (C语言)字符分类函数
  • (二)hibernate配置管理
  • (附源码)php投票系统 毕业设计 121500
  • (附源码)spring boot网络空间安全实验教学示范中心网站 毕业设计 111454
  • (转)jdk与jre的区别
  • ***详解账号泄露:全球约1亿用户已泄露
  • *_zh_CN.properties 国际化资源文件 struts 防乱码等
  • .Net Core和.Net Standard直观理解
  • .NET NPOI导出Excel详解
  • .Net中的设计模式——Factory Method模式
  • @autowired注解作用_Spring Boot进阶教程——注解大全(建议收藏!)
  • @Data注解的作用
  • [ 2222 ]http://e.eqxiu.com/s/wJMf15Ku
  • [ 攻防演练演示篇 ] 利用通达OA 文件上传漏洞上传webshell获取主机权限
  • [20170705]lsnrctl status LISTENER_SCAN1
  • [AutoSar]BSW_Memory_Stack_004 创建一个简单NV block并调试
  • [C# 基础知识系列]专题十六:Linq介绍