c++未加载ntdll.pdb_JS - Module的加载实现

v2-d09dec6e8022ce04068961587d0a81ed_1440w.jpg?source=172ae18b

《ES6 标准入门》CH23 Module的加载实现

1、浏览器加载

传统方法是script标签,浏览器遇到标签时,会下载好js文件,执行完了,然后回到网页上继续往下渲染,这样会造成假死,用户体验不好。如果用了defer,会等到网页执行完了再按照引用顺序执行所有defer的js,如果用了async,会等到js下载好了之后立即中断网页渲染,去执行js,执行完了再回来渲染。defer是保序的,一定会按照引用顺序执行,async是不保证顺序的,按照下载完成的先后执行。

浏览器直接加载ES6模块要用,type="module"标签,这个标签默认是defer的,但是也用关键字async指定执行方式为async。这么引用可以用外部的ES6模块文件,也可以在script标签里直接写ES6模块的代码,这里写的模块,用import不能省略.js后缀,作用域是算在模块内部,不算全局,因为ES6模块默认使用严格模式运行,顶层this会是undefined而非window。

2、ES6模块与CommonJS模块的差异

CommonJS是值的复制,输出的那一刻是什么就是什么了,export语句后面改它,外面的引用方都是拿不到的,ES6模块输出的是引用,CommonJS得执行生成对象才能用,所以是运行之后有对象了才能加载,ES6是静态编译阶段就有这个引用(书中一直将ES6的输入描述为接口)了。

又因为ES6输出的是引用,所以B跟C同时引用了A的某个东西,它们是相等的。

3、Node加载

Node自己用的是CommonJS,这玩意儿跟ES6的模块不兼容=-=。目前是ES6模块跟CommonJS各自采用自己的加载方案。对于Node说只要包含了import/export,就认为是一个ES6模块,所以可以写一条没有意义的export {};,把这个模块指定为ES6。需要注意,ES6的顶层this是undefined,CommonJS里的顶层this指向当前模块。

用import加载CommonJS,会认为CommonJS里面写的module.exports就是export default。也因此只能整体的import,就是import *用法,不能import一个特定的东西比如import {readfile} from 'fs';,因为fs是个CommonJS模块要等运行的时候才能确定,但是import这句话是在静态分析阶段就执行的,所以找不到=-=。还有就是,因为被引用的其实是个CommonJS对象,所以CommonJS的缓存机制,仍然有效。

用require方式加载ES6模块,首先被引用的ES6模块里所有export的东西会被放在一个对象里,然后会有缓存机制,export了之后,再改这个变量,不认。

感觉Node的思路是我用的就是CommonJS,我只是兼容ES6,所以混合用的时候,往CommonJS的方向靠拢,都是值的缓存,而非引用。

4、循环加载

循环加载就是相互依赖,A依赖B,B依赖A。

先说CommonJS的加载原理,第一次require某个模块的时候,执行这个模块,生成一个缓存对象,下次别人再require这个模块,不会再执行,会把这个缓存对象再扔给别人用。

然后是CommonJS的循环加载,入口是a,a引用b的时候在b里执行,这时候发现b引用了a,查了一下发现a已经正在执行了,那就只把a目前的执行结果拿过来,后面还有啥东西就不管了,这样破坏的循环。所以,对于a只输出已执行的部分,未执行的部分不会输出。

ES6模块的循环加载,这个我有一点迷茫。。。感觉也是,入口为a,a引用b,b再引用a的时候,a的某些值可能因为没有执行到而没有,但是a的函数就能用。。。非常奇怪没看懂

5、ES6的转码

浏览器目前不支持ES6模块,得转码。

可以用ES6 module transpiler或者SystemJS,它们都是转换转换器。后者的System.import使用异步加载,返回一个Promise对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值