ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CommonJS 和ES6 MODULE的使用以及区别

2022-03-06 04:00:16  阅读:211  来源: 互联网

标签:function ES6 CommonJS exports MODULE export 模块 import 加载


CommonJS 使用方式

注意:是exports不是export

导出

 //通过module.exports导出一个对象,对象存放功能函数或数据或某个具体的值
//引入时通过自定义变量obj.fn1()使用即可
module.exports = { 
  fn1: function () {
    console.log("fn1")
  },
  flag: true,
  arr: [],
}

//亦可通过exports直接导出,exports本质上是node实现的module.exports的简写,相当于var exports = module.exports
exports.fn2 = function () {
  console.log("fn2")
}

function mod1(){console.log(1);}
function mod2(){console.log(2);}
module.exports={mod1:mod1,mod2:mod2}

引入

const express = require("express")      //express 是node第三方模块,直接引入模块名即可

const obj = require("模块文件路径")       // 引入自定义模块时,require函数的参数为模块的文件路径,引入了模块文件并赋值给自定义变量obj 

var {mod1,mod2} = require('./t');

ES6 MODULE使用方式

导出

第一种 - 直接导出
export var firstName = 'Michael';
export function multiply(x, y) { return x * y;};

第二种 - 使用{}导出
export { firstName, multiply };

注意:不可以直接导出export 1,也不可以直接export m

// 报错
export 1;

// 报错
var m = 1;
export m;

正确
// 写法一
export var m = 1;

// 写法二
var m = 1;
export {m};

// 写法三
var n = 1;
export {n as m};

引入

import { firstName, lastName, year } from './profile.js';

别名
import { lastName as surname } from './profile.js';

注意:不允许在加载模块的脚本里面,改写接口。

可以直接理解成,通过ES6 MODULE引入的都是用const申明过。

import {a} from './xxx.js'
a = {}; // Syntax Error : 'a' is read-only;
a.foo = 'hello'; // 合法操作

注意:如果想在一条import语句中,同时输入默认方法和其他接口,可以写成下面这样。

先写不带括号,再写带括号的

import _, { each, forEach } from 'lodash';

export default的使用

// 第一组
export default function crc32() { // 输出
  // ...
}

import crc32 from 'crc32'; // 输入

// 第二组
export function crc32() { // 输出
  // ...
};

import {crc32} from 'crc32'; // 输入

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

非匿名
export default function foo() {
  console.log('foo');
}
匿名
export default function () {
  console.log('foo');
}

export 与 import 的复合写法

export { foo, bar } from 'my_module';

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

CommonJS和ES6 MODULE差异

  1. CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
  2. CommonJS 模块是运行时加载(动态加载),ES6 模块是编译时输出接口(静态加载)。
  3. CommonJS 模块的require()是同步加载模块,ES6 模块的import命令是异步加载,有一个独立的模块依赖的解析阶段。

ES2020支持import动态导入,详情

动态加载会得到的是一个promise对象,并且也支持await,这样就可以实现按需加载(懒加载)

import静态导入
import xxx from 'xxx.js'
import {xx,x} from 'xxx.js'

import动态导入
import(xxx.js)

动态导入和静态导入的区别

import在静态解析阶段执行,所以它是一个模块之中最早执行的,而动态这是在执行到对于代码时再去请求。

CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成,也就是说要运行全部代码才能确定module.exports的完整性。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成(按需加载)。

值的拷贝和值的引用的区别

import和require都是会执行一遍代码,只是一个是在运行时执行(耽误时间),一个是编译时解析(达到按需导入,优化运行速度)。

在两种方式都引入需要的内容时,不管是当做整体还是使用{}选取部分,CommonJS 模块输出的是值的拷贝,运行完模块后,值会缓存在本地,注意原始类型的值,会被缓存,函数不会缓存到本地,所以执行的时候还是去内存找到原本存储位置,这样才能改变模块中的内容,不然的话,及时写了一个如下面代码那样改变模块内容的代码,但是由于函数也被拷贝到了新内存中,这样就找不到需要改变的模块内的那个值了,那就表示模块写死了,无法改变,但事实并非如此。也就是说,一旦输出一个值,模块内部的变化就影响不到这个值,除非采用刚刚说的方式。

CommonJS获取模块变动后的值

需要使用一个取值函数,不然会一直取到缓存好的值。

// lib.js
var counter_num = 3;
function incCounter() {counter_num++;}
function counter() {return counter_num}
module.exports = {counter,incCounter,};

var mod = require('./lib');
console.log(mod.counter());  // 3
mod.incCounter();
console.log(mod.counter()); // 4

ES6则如同是将引入文件中选择好的代码注入被引入文件里一样,JS 引擎对脚本静态分析的时候,遇到模块加载命令import,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。

换句话说,ES6 的import有点像 Unix 系统的“符号连接”,原始值变了,import加载的值也会跟着变。因此,ES6 模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。

标签:function,ES6,CommonJS,exports,MODULE,export,模块,import,加载
来源: https://www.cnblogs.com/EQ1024/p/15970242.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有