Node之全局对象和模块化细节
Node之全局对象
Node 和浏览器类似,有许多全局对象。例如 global ,它可以使用 global 访问自己,原因是它将自己复制给了 global ,和 window 类似。
计时器有 setTimeout ,setInterval ,setImmediate ,setImmediate 类似于 setTimeout 0 的情况。console 输出相关,__dirname,当前模块所在目录,__filename 当前模块所在文件,这两个都不是 global 属性,Buffer 是继承自类型化数组。它正好是一个字节的单位,输入输出都使用2位的16进制数字表示。
还有和 Node 进程相关的函数 process 。比如 cwd() 返回 Node 当前进程的目录,exit() 退出当前进程,默认0表示正常,1表示发生错误,argv 可以得到命令行参数的信息,platform 得到所在的操作系统,指的是某个平台,例如 win32 指的是 32 位以上的系统,kill(pid) 可以杀死进程,需要传入进程 ID ,每次进程 ID 都不相同,env 可以获取环境变量。
Node之模块化细节
导入模块可以分为绝对路径和相对路径导入模块。相对路径可以分为 当前目录 ./ 或上一级目录 ../ 导入模块,它的模块也是转换为绝对路径导入。
还有一种导入模块的方式是从内置模块查找,然后在当前目录以及上一级目录查找 node_modules ,也是转换为绝对路径导入。
后缀名会自动补齐。查找顺序为js,json,node,mjs。如果是一个目录,没有写文件名,则会使用 index.js 来进行补齐。
如果是导入或执行一个包的时候,只提供目录会从 main 里面查找默认路径,默认值为 index.js 。
module 是一个内置对象,我们不可以使用它。内部有id,表示当前模块的绝对路径,path,当前目录,exports,导出, parent,这个文件的入口文件,id为 . ,在打印结果时还没有加载完,所以 loaded 为 false ,children 为一个递归,paths 当你查找一个包时的顺序。
require 是一个函数。resolve 方法会把绝对路径转换为相对路径,main 是入口模块的信息,extensions 是扩展名的处理函数,cache 是缓存结果,会将绝对路径的 id 作为属性名,对应的模块作为属性值。
function require(modulePath) {
//1.将module Path转换成绝对路径
require.cache={};
//2.判断该模块是否有缓存,如果有缓存,返回缓存结果
if (require.cache['绝对路径']) {
return require.cache['绝对路径'].result;
}
//3.读取模块文件内容
//4.将模块内容转为函数
function __temp(module, exports, require, __dirname, __filename) {
//文件内容
}
//5.创建module对象
module.exports = {};
const exports = module.exports;
__temp.call(module.exports, module, exports, require, module.path, module.filename)
return module.exports;
}
const result=require('./myModule.js');
console.log(result);
模块化是如何实现的。首先会拿到绝对路径,接着找相关缓存,如果没有缓存会读取文件内容,接着将内容放在一个函数内,这也就是我们为什么可以直接调用这些属性但不在 global 中。最后创建 module 对象。这个对象中 this 和 exports 和 module.exports 一开始都是一样的,但如果改变 module.exports 之后,就会改变它的值,但 this 和 exports 还是原来的值。因为返回的是 module.exports ,所以就会导致和 this,exports 值不一样。如果改变了 exports 值之后,也会使得和 this 值不一样。
ES模块化
目前有两种方式实现模块化,一种是 common JS ,另一种是 ES 。将一个文件后缀名改为 .mjs ,就可以实现一个模块的 ES模块化,或者在 package.json 中将 type 的值设置为 module ,将整个工程设置为 ES 模块。
两种模块无法兼容在于 ES 并没有将模块当作一个函数。运行模块时,需要添加 --experimental-modules 指令。
可以使用js导出到mjs,但导入mjs不行。
// import obj from './a1.js'
// console.log(obj.a)
import('./a1.js').then(r=>console.log(r))
还可以使用动态异步的方式进行导入。