# This is JavaScript notes
# ESM vs CJS
# 相互引用
ESM
模块只能import
而不能require
。ESM
模块可以import
CJS
模块,但是只能通过默认导入的模式,比如import _ from 'lodash'
,而不能使用声明式的导入方式,比如import {shuffle} from 'lodash'
。(That’s because CJS scripts compute their named exports as they execute, whereas ESM’s named exports must be computed during the parsing phase. )ESM
模块可以require
CJS
模块,包括声明式导出的,但是依然会有很多问题,类似 Webpack 或者 Rollup 这样的工具甚至不知道该怎么出处理ESM
里的require
代码。Node 默认支持的是
CJS
标准,你需要选择.mjs
这样的后缀或者在package.json
文件中设置"type": "module"
才能开启ESM
模式。通过这种方式开启的话,如果有CJS
规范的文件,就需要将后缀改成.cjs
。
# 加载
CJS
中的 require
是同步的,他不会返回一个 promise
或者是执行一个回调函数。require
从磁盘或者网络中读取文件然后立即执行。
ESM
中的模块 loader
异步加载模块,首先解析 import
和 export
而不是去执行,在解析阶段,模块 loader
可以在声明式的 import
中检测错误并且抛出而不运行任何依赖的代码。
The ESM module loader then asynchronously downloads and parses any scripts that you imported, and then scripts that your scripts imported, building out a “module graph” of dependencies, until eventually it finds a script that doesn’t import anything. Finally, that script is allowed to execute, and then scripts that depend on that are allowed to run, and so on.
ES 模块中所有的依赖是并行下载,最后按顺序执行。
# 差异
CJS
不能 require
ESM
最大的原因是 CJS
不支持 Top-level await。
(async () => {
const {foo} = await import('./foo.mjs');
})();
# ES 模块中实现 require
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const {foo} = require('./foo.cjs');
# Promise
Promise.catch
只是 promise.then(undefined, onRejected);
方法的一个别名。也就是说,这个方法用来注册当 promise
对象状态变为 Rejected
时的回调。
静态方法 Promise.resolve(value)
可以认为是 new Promise()
方法的快捷方式。
Promise.resolve('foo');
new Promise((resolve) => { resolve('foo') });
每次调用 then
方法都会返回一个新promise
对象。
# let、const、var
var
定义的变量可以先使用后定义
let
定义变量必须先定义后使用
const
定义的变量值不能进行修
# const修饰的对象属性可以修改,为什么
可以修改,原因:const指针指向的地址不可以改变,指向地址的内容是可以改变的。因为const只是保证对象的指针不改变,而对象的内容改变不会影响到指针的改变,所以对象的属性内容是可以修改的。