Node中的模块使用

2021-08-02  本文已影响0人  薯条你哪里跑

1.概述

node默认使用的是commonjs模块规范。每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。

如果要共享只能挂在全局变量global上(不推荐这种做法ヽ(`Д´)ノ):

global.plat = “PC”;

或者通过模块引用的方式(推荐(๑•̀ㅂ•́)و✧):。

CommonJS规范规定,每个模块内部,module变量代表当前模块。这个变量是一个对象,它的exports属性(即module.exports)是对外的接口。加载某个模块,其实是加载该模块的module.exports属性。

2. 加载

CommonJS使用require来引入模块,使用exportsmodule.exports来导出模块(module);

const { read, write } = require('./file');

CommonJS只能在运行时才能确定模块的引用及依赖关系。上述代码其实是先加载file这个整个对象,之后再取上面的属性。

const file = require('./file');
const read  =   file.read
const write  =   file.write

ps: 但是es6是通过export命令直接导出,在编译时就可以判断要加载的方法即我们所说的静态编译。为后续的类型校验和宏提供了可能

3.module

Node内部有个Module的构造函数,每个文件中的module都是其的一个实例,module有以下几个属性:

随便找个文件,打印一下console.log(module)
Module {
  id: '/Users/pub/f-node-encryption/dist/index.js',
  path: '/Users/pub/f-node-encryption/dist',
  exports: {},
  parent: Module {
    id: '.',
    path: '/Users/pub/f-node-encryption/test',
    exports: {},
    parent: null,
    filename: '/Users/pub/f-node-encryption/test/index.js',
    loaded: false,
    children: [ [Circular] ],
    paths: [
      '/Users/pubf-node-encryption/test/node_modules',
      '/Users/pub/f-node-encryption/node_modules',
      '/Users/pub/node_modules',
      '/Users/node_modules',
      '/node_modules'
    ]
  },
  filename: '/Users/pub/f-node-encryption/dist/index.js',
  loaded: false,
  children: [
    Module {
      id: '/Users/pub/f-node-encryption/dist/src/lib/util.js',
      path: '/Users/pub/f-node-encryption/dist/src/lib',
      exports: [Object],
      parent: [Circular],
      filename: '/Users/pub/f-node-encryption/dist/src/lib/util.js',
      loaded: true,
      children: [Array],
      paths: [Array]
    }
  ],
  paths: [
    '/Users/pub/f-node-encryption/dist/node_modules',
    '/Users/pub/f-node-encryption/node_modules',
    '/Users/pub/node_modules',
    '/Users/node_modules',
    '/node_modules'
  ]
}

node引用模块很简单,在文件内部使用exportsmodule.exports来导出。举个🌰

// a.js  定义一个TestClass类
class TestClass {
  constructor(){}
  .....
}
 module.exports = TestClass

// b.js 引用并实例化
const  TestClass = require("./a")
cosnt curTest =  new  TestClass()
....
console.log(exports===module.exports)  // 输出true

这里使用module.exports来进行导出,当然也可以使用 exports, 但是!!!我们不能直接给 exports赋值,像这样:

exports = TestClass

这是不可以的!!!因为使用的exports其实是module.exports的引用,如果直接赋值会使引用断开,此时在b.js内打印TestClass会输出module.exports的值,此时就是一个空对象。

再次重申,模块导出导出的是module.exports的值!!!

当然在保留引用的前提下可以进行赋值:

// a,js
exports.test = TestClass

// b.js 
const  TestClass = require("./a")
cosnt curTest =  new  (TestClass.test)()

4. CommonJS模块的特点。

主要有以下三点:

关于第二条还想仔细说一下

举个缓存的🌰:

// a.js
var tmp = {name::“Jack”};
module.exports = tmp; 

// b.js
const OnceTest = require("./a")
// 输出OnceTest为 {name:“Jack”}
console.log("OnceTest:", OnceTest) 
// 给 OnceTest添加新的属性
OnceTest.age = 21;   
// 再次引入相同模块
const TwiceTest = require("./a")
// 此时打印TwiceTest,发现里面也有age属性
console.log("TwiceTest:", TwiceTest)  // 输出{name:“Jack”, age:21} 

如果我想清除缓存那么需要修改下b.js:

const OnceTest = require("./a")
console.log("OnceTest:", OnceTest) 
OnceTest.age = 21;   
// 先要清除引入模块的缓存
delete require.cache['/Users/pub/f-node-encryption/a.js']
// 再次引入相同模块
const TwiceTest = require("./a")
// 此时打印TwiceTest,发现已经是从a.js新引入的模块了
console.log("TwiceTest:", TwiceTest)  // 输出{name:“Jack”} 

详细cache里的内容可以打印require.cache查看。
这里贴一个清除缓存时存在的问题 传送门

4.顺便记一下ES中的模块使用

在ES中的模块使用相对灵活,使用export export detault来导出,使用import来引用。

我们先看一下exportexport default这两个导出方式有什么不同

// 导出变量
export const a = 123;
// 导出方法
export const getName = function(){}
// 导出方法
function getName(){}
export {getName}

// excport default 导出变量
const a = 123;
export default a
// 导入
// 使用 export 方法导出
import { dogSay, catSay } from './test'; 
// 使用export default导出
import a from './test';  
// as 集合成对象导出
import * as testModule from './test'; //as 集合成对象导出

其他细节不再次赘述啦,感兴趣的小伙伴自行学习;
还有一点需要注意一下,因为import是静态解析的,所以在引入前使用也是不会报错的:

dogSay()
import { dogSay, catSay } from './test';

但是 不可以在这样“动态”使用import

const  moduleName = "dog"
import { `${moduleName}Say` } from './test';
// 或者这样
if(moduleName === "dog"){
  import { dogSay`} from './test';
}

写的有点凌乱回头在整理一波= =

上一篇 下一篇

猜你喜欢

热点阅读