首页 > 其他 > 详细

深入ES Module

时间:2021-06-05 11:16:58      阅读:14      评论:0      收藏:0      [点我收藏+]
  • ES Module和CommonJS的模块化有一些不同之处:
    • 一方面它使用了import和export关键字;
    • 另一方面它采用编译期的静态分析,并且也加入了动态引用的方式;

一、ES Module模块采用export和import关键字来实现模块化:

  • export负责将模块内的内容导出;
  • import负责从其他模块导入内容;

三种导出方式:

const name = "why";
const age = 18;
const sayHello = function(name) {
  console.log("你好" + name);
}

// 导出方式三种
// 1.方式一:
// export const name = "why";
// export const age = 18;
// export const sayHello = function(name) {
//   console.log("你好" + name);
// }

// 2.方式二: {}中统一导出
// {}大括号, 但是不是一个对象
// {放置要导出的变量的引用列表}
export {
  name,
  age,
  sayHello
}

// 3.方式三: {} 导出时, 可以给变量起名别
// export {
//   name as fName,
//   age as fAge,
//   sayHello as fSayHello
// }

export default function() {
  console.log("对某一个东西进行格式化");
}

三种导入方式:

// 常见的导入方式也是有三种
// 方式一: import {} from ‘路径‘;
// import { name, age, sayHello } from ‘./modules/foo.js‘;

// 方式二: 导出变量之后可以起别名
// import { name as wName, age as wAge, sayHello as wSayHello } from ‘./modules/foo.js‘;
// import { fName as wName, fAge as wAge, fSayHello as wSayHello } from ‘./modules/foo.js‘;

// 方式三: * as foo
// import * as foo from ‘./modules/foo.js‘;

// console.log(foo.name);
// console.log(foo.age);
// foo.sayHello("王小波");


// 演练: export和import结合使用
import { name, age, sayHello } from ‘./modules/bar.js‘;

console.log(name);
console.log(age);
console.log(sayHello);


// 演练: default export如何导入
import format from ‘./modules/foo.js‘;
format();


二、Export和import结合使用

  • 为什么要这样做呢?
    • 在开发和封装一个功能库时,通常我们希望将暴露的所有接口放到一个文件中;
    • 这样方便指定统一的接口规范,也方便阅读;
    • 这个时候,我们就可以使用export和import结合使用
// 演练: export和import结合使用
import { name, age, sayHello } from ‘./modules/foo.js‘;

 console.log(name);
 console.log(age);
 console.log(sayHello);

三、通过import加载一个模块,是不可以在其放到逻辑代码中的

  • 为什么会出现这个情况呢?
    • 这是因为ES Module在被JS引擎解析时,就必须知道它的依赖关系;
    • 由于这个时候js代码没有任何的运行,所以无法在进行类似于if判断中根据代码的执行情况;
    • 甚至下面的这种写法也是错误的:因为我们必须到运行时能确定path的值;
  • 但是某些情况下,我们确确实实希望动态的来加载某一个模块:
    • 如果根据不懂的条件,动态来选择加载模块的路径;
    • 这个时候我们需要使用 import() 函数来动态加载;
// 演练: import()函数
let flag = true;
if (flag) {
  // require的本质是一个函数
  // require(‘‘)

  // 执行函数 
  // 如果是webpack的环境下: 模块化打包工具: es CommonJS require()
  // 纯ES Module环境下面: import(), 这里的import是个函数,返回的是promise
  // 脚手架 -> webpack: import()
  import(‘./modules/foo.js‘).then(res => {
    console.log("在then中的打印");
    console.log(res.name);
    console.log(res.age);
  }).catch(err => {

  })
}

四、ES Module加载过程

  • ES Module加载js文件的过程是编译(解析)时加载的,并且是异步的:

    • 编译时(解析)时加载,意味着import不能和运行时相关的内容放在一起使用:
    • 比如from后面的路径需要动态获取;
    • 比如不能将import放到if等语句的代码块中;
    • 所以我们有时候也称ES Module是静态解析的,而不是动态或者运行时解析的;
  • 异步的意味着:JS引擎在遇到import时会去获取这个js文件,但是这个获取的过程是异步的,并不会阻塞主线程继续执行;

    • 也就是说设置了 type=module 的代码,相当于在script标签上也加上了 async 属性;
    • 如果我们后面有普通的script标签以及对应的代码,那么ES Module对应的js文件和代码不会阻塞它们的执行;
  • ES Module通过export导出的是变量本身的引用:

    • export在导出一个变量时,js引擎会解析这个语法,并且创建模块环境记录(module environment record);
    • 模块环境记录会和变量进行 绑定(binding),并且这个绑定是实时的;
    • 而在导入的地方,我们是可以实时的获取到绑定的最新值的;
  • 所以,如果在导出的模块中修改了变化,那么导入的地方可以实时获取最新的变量;

  • 注意:在导入的地方不可以修改变量,因为它只是被绑定到了这个变量上(其实是一个常量)

  • 如果bar.js中导出的是一个对象,那么main.js中是否可以修改对象中的属性呢?

    • 答案是可以的,因为他们指向同一块内存空间;

技术分享图片

深入ES Module

原文:https://www.cnblogs.com/107w/p/14851661.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!