前端模块化(Es-Module和CommonJs)

1.没有模块化出现的问题以及解决方案和该解决方案的缺点

2.CommonJs

3.Es-Module

1.没有模块化出现的问题以及解决方案和该解决方案的缺点

1)问题:容易出现命名冲突

2)解决方案和缺点:用立即执行函数,缺点:解决了一部分命名冲突,但是还是容易冲突    使用的时候需要去查看那个导入的文件内名字   代码混乱不堪

2.CommonJs

1)exports和module.exports

(1)关系:在CommonJs规范里面是没有exports的,node为了实现这个规范,于是用了module的类,在实际导出中,其实导出的是module.exports而不是exports

他们在文件的初始中使用了module.exports=exports,所以如果用module.exports导出一个对象的时候,对于exports导出的内容在导入的文件中是接收不到的,并且当exports导出一个对象的时候导入的文件也是接收不到的

//module.exports的导出
module.exports = {}
module.exports.name='name'
//exports的导出
exports.name = 'name'

2)require

导入文件,在导入的时候,被导入的文件首先会执行一遍

const name= require("./name.js")

当出和导入的对象是同一个对象,所以不管这个对象在哪里,如果对这个对象做了修改操作。其他文件内也会发生变化

查找规则:1)如果是require(X)X如果是一个node模块,直接会导入这个模块  如果不是,会在当前目录底下寻找node_modules,如果没找到就到上一层查找,直到最顶层,还没找到的话报错  2) 如果带./等相对路径,有后缀名的情况下,会准确查找,找不到就报错  带后缀名的话,例如./main会按照以下顺序查找:./main  ./main.js  ./main.json  ./main.node  ./main/index.js  ./main/index.json  ./main.node

3)模块的加载过程:

a.模块导入就会执行一次

b.多次加载,会被缓存,最终还是只执行一次,因为每个模块都有loaded属性,如果加载过了就会变true,否则是false

c.如果循环引入,有两种遍历方法,一个是深度优先,另外一个就是广度优先,node采用的是深度优先,就是main里面加载了a和b,从上到下执行加载,比如a的require在上面,就先加载a,如果a模块还加载了c模块。就加载c模块,当c模块加载完了再加载b模块

4)缺点:CommonJs的加载是同步加载,如果是在服务器,因为是本地文件,所以没有影响,但是如果在浏览器,我们需要去下载文件,会阻塞后面代码的执行,因此在浏览器以前采用AMD或CMD,现在浏览器已经实现了Es-Module或者靠webpack转换CommonJs和EsModule   导出后依旧可以更改,不好溯源

3.Es-Module

补充:在本地测试的时候,要对本地开一个服务器   要使用live Server  不然会报错

1.export和export default

export导出:一个个导出 或 一下子导出  导出的时候起别名

//一个个导出
export const namePerson='小红'
wxport function foo(){}
//一下子导出
const namePerson='小红'
function foo(){}
export {
namePerson,
foo
}
//不能这样导出
//export {
//namePerson:'小红',
//}
//起别名
const a=1
export {
a as b
}

export default:默认导出

const a=1
export default {
a
}

注意一下子导出的时候虽然有个大括号 但是不是代表那是对象 那不是一个对象 导入也是,只是存放导入的标识符列表内容,而不是对象

2.import

导入解构   一下子导入全部   起别名  以及默认导入

//导入解构
import {a} from './main.js'
//一下子导入
import * as a from './main.js'
//导入起别名
import {a as b} from './main.js'
//默认导入
import a from './main.js' 

3.import动态导入和import.meta

 import函数返回的结果是一个Promise  meta属性很多时候里面不仅仅有url

import("./foo.js").then(res => {
  console.log("res:", res.name)
})

console.log("后续的代码都是不会运行的~")

// ES11新增的特性
// meta属性本身也是一个对象: { url: "当前模块所在的路径" }
console.log(import.meta,88)

 动态导入是不会在解析的时候构建的,只有在执行的时候才构建

4.浏览器请求的时候的解析流程

分为三个部分:解构阶段   实例化阶段   求值阶段

1)构建阶段:静态分析引用,解析成模块环境记录,当一个文件被下载后不会重复下载,因为有做缓存,什么是静态分析,就是编译时加载,代表import不能和运行时相关内容放一起使用,并且是异步的

2)实例化阶段:在内存里面创建对象,把模块指向内存对象,绑定是实时的,导出修改了,那么导入可以获取到最新值,但是导入不能修改值,除非是引用类型

3)求值阶段:执行模块,对模块内的变量求值

5.Commonjs和EsModule相互引用

node某些版本使用EsModule:方式一:在package.json中配置 type: module   方式二:文件以 .mjs 结尾,表示使用的是ES Module

对于相互引用,在浏览器内不能,因为浏览器不支持Commonjs,在node里面要区分版本,高版本可以,在webpack里面可以相互引用,因为webpack会转化

6.CommonJS和ES Module交互

结论一:通常情况下,CommonJS不能加载ES Module
因为CommonJS是同步加载的,但是ES Module必须经过静态分析等,无法在这个时候执行JavaScript代码;
但是这个并非绝对的,某些平台在实现的时候可以对代码进行针对性的解析,也可能会支持;
Node当中是不支持的;
结论二:多数情况下,ES Module可以加载CommonJS
ES Module在加载CommonJS时,会将其module.exports导出的内容作为default导出方式来使用;
这个依然需要看具体的实现,比如webpack中是支持的、Node最新的Current版本也是支持的;
但是在最新的LTS版本中就不支持;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值