node

1869 字
9 分钟
node

node简介#

Node是对ES标准一个实现,Node也是一个JS引擎,通过Node可以使js代码在服务器端执行,Node仅仅对ES标准进行了实现,所以在Node中不包含DOM 和 BOM

node的模块化#

在Node中,一个js文件就是一个模块

每一个js文件中的js代码都是独立运行在一个函数中而不是全局作用域,所以一个模块的中的变量和函数在其他模块中无法访问

CommonJS#

模块就是一个js文件,在模块内部任何变量或其他对象都是私有的,不会暴露给外部模块。

在CommonJS模块化规范中,在模块内部定义了一个module对象,module对象内部存储了当前模块的基本信息,同时module对象中有一个属性名为exports,exports用来指定需要向外部暴露的内容。只需要将需要暴露的内容设置为exports或exports的属性,其他模块即可通过require来获取这些暴露的内容。

加载模块#

使用 require() 方法,可以加载需要的内置模块、用户自定义模块、第三方模块进行使用。

注意:使用 require() 方法加载其它模块时,会执行被加载模块中的代码。

// 加载内置 fs 模块
const fs = require('fs')
// 加载自定义模块
const m = require('./myModule.js')
// 加载第三方模块
const moment = require('moment')
// 通过解构赋值按需加载模块
const { a, b } = require('./myModule.js')

module 对象#

在每个 .js 自定义模块中都有一个 module 对象,它里面存储了和当前模块有关的信息,打印如下

console.log(module)
// output
Module {
id: '.',
path: 'D:\\study\\nodejs\\moudle',
exports: {},
parent: null,
filename: 'D:\\study\\nodejs\\moudle\\myMoudle.js',
loaded: false,
children: [],
paths: [
'D:\\study\\nodejs\\moudle\\node_modules',
'D:\\study\\nodejs\\node_modules',
'D:\\study\\node_modules',
'D:\\node_modules'
]
}

module.exports对象#

在自定义模块中,可以使用 module.exports 对象,将模块内的成员共享出去,供外界使用。

外界用 require() 方法 导入自定义模块时,得到的就是 module.exports 所指向的对象。

const a = 10
const b = 20
const obj = { name: "孙悟空" }
module.exports.a = a
module.exports.b = b
// const {a, b} = require("./m.js")
const a = 10
const b = 20
const obj = { name: "孙悟空" }
module.exports = { a, b, obj}
// const {a, b, obj} = require("./m.js")

默认情况下,Node.js会将以下内容视为CommonJS模块:

  1. 使用.cjs为扩展名的文件
  2. 当前的package.json的type属性为commonjs时,扩展名为.js的文件
  3. 当前的package.json不包含type属性时,扩展名为.js的文件
  4. 文件的扩展名是mjs、cjs、json、node、js以外的值时(type不是module时)

exports 对象#

由于 module.exports 单词写起来比较复杂,为了简化向外共享成员的代码,Node 提供了 exports 对象。

默认情况 下 , exports 和 module.exports 指向同一个对象 。最终共享的结果,还是以 module.exports 指向的对象为准

console.log(module.exports === exports) // true
const a = 10
const b = 20
const obj = { name: "孙悟空" }
exports.a = a
exports.b = b
// const {a, b} = require("./m.js")

exports 和 module.exports 的使用误区#

时刻谨记,require() 模块时,得到的永远是 module.exports 指向的对象

exports.obj = { name: '孙悟空' }
module.exports = {
a: 10,
b: 20,
}
// const m = require("./m.js")
// console.log(m) // { a: 10, b: 20 }

**注意:**为了防止混乱,建议不要在同一个模块中同时使用 exports 和 module.exports

文件作为模块#

当我们加载一个自定义的文件模块时,模块的路径必须以/、./或../开头。如果不以这些开头,node会认为你要加载的是核心模块或node_modules中的模块。

当我们要加载的模块是一个文件模块时,CommonJS规范会先去寻找该文件,比如:require("./m1")时,会首先寻找名为m1的文件。如果这个文件没有找到,它会自动为文件添加扩展名然后再查询。扩展名的顺序为:js、json、node。

还是上边的例子,如果没有找到m1,则会按照顺序搜索m1.js、m1.json、m1.node哪个先找到则返回哪个,如果都没有找到则报错。

文件夹作为模块#

当我们使用一个文件夹作为模块时,文件夹中必须有一个模块的主文件。如果文件夹中含有package.json文件且文件中设置main属性,则main属性指定的文件会成为主文件,导入模块时就是导入该文件。如果没有package.json,则node会按照index.js、index.node的顺序寻找主文件。

Node_modules#

如果我们加载的模块没有以/、./或../开头,且要加载的模块不是核心模块,node会自动去node_modules目录下去加载模块。

node会先去当前目录下的node_modules下去寻找模块,找到则使用,没找到则继续去上一层目录中寻找,以此类推,知道找到根目录下的node_modules为止。

比如,当前项目的目录为:'C:\Users\lilichao\Desktop\Node-Course\myProject\node_modules',则模块查找顺序依次为:

‘C:\Users\lilichao\Desktop\Node-Course\node_modules’,
‘C:\Users\lilichao\Desktop\node_modules’,
‘C:\Users\lilichao\node_modules’,
‘C:\Users\node_modules’,
‘C:\node_modules’

模块的包装#

每一个CommonJS模块在执行时,外层都会被套上一个函数:

(function(exports, require, module, __filename, __dirname) {
// 模块代码会被放到这里
})

所以我们之所以能在CommonJS模块中使用exports、require并不是因为它们是全局变量。它们实际上以参数的形式传递进模块的。

exports,用来设置模块向外部暴露的内容

require,用来引入模块的方法

module,当前模块的引用

__filename,模块的路径

__dirname,模块所在目录的路径

ES模块化#

2015年随着ES6标准的发布,ES的内置模块化系统也应运而生,并且在Node.js中同样也支持ES标准的模块化。

需要注意的是,Node.js默认并不支持ES模块化,如果需要使用可以采用两种方式。

方式一,直接将所有的js文件修改为mjs扩展名。

方式二,修改package.json中type属性为module。

导出#

// 导出变量(命名导出)
export let name1, name2, …, nameN;
export let name1 = …, name2 = …, …, nameN;
// 导出函数(命名导出)
export function functionName(){...}
// 导出类(命名导出)
export class ClassName {...}
// 导出一组
export { name1, name2, …, nameN }
// 重命名导出
export { variable1 as name1, variable2 as name2, …, nameN }
// 解构赋值后导出
export const { name1, name2: bar } = o
// 默认导出
export default expression
export default function (…) { … } // also class, function*
export default function name1(…) { … } // also class, function*
export { name1 as default, … };
// 聚合模块
export * from …; // 将其他模块中的全部内容导出(除了default)
export * as name1 from …; // ECMAScript® 2O20 将其他模块中的全部内容以指定别名导出
export { name1, name2, …, nameN } from …; // 将其他模块中的指定内容导出
export { import1 as name1, import2 as name2, …, nameN } from …; // 将其他模块中的指定内容重命名导出
export { default, … } from …;

引入#

// 引入默认导出
import defaultExport from "module-name"
// 将所有模块导入到指定命名空间中
import * as name from "module-name"
// 引入模块中的指定内容
import { export1 } from "module-name"
import { export1 , export2 } from "module-name"
// 以指定别名引入模块中的指定内容
import { export1 as alias1 } from "module-name"
import { export1 , export2 as alias2 , [...] } from "module-name"
// 引入默认和其他内容
import defaultExport, { export1 [ , [...] ] } from "module-name"
import defaultExport, * as name from "module-name"
// 引入模块
import "module-name"

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

node
https://sukksa.github.io/posts/node/
作者
Sukksa
发布于
2021-11-19
许可协议
CC BY-NC-SA 4.0
相关文章智能推荐
1
react-hooks
reactReact 的核心是组件。v16.8 版本之前,组件的标准写法是类(class)。 任何一个组件,可以用类来写,也可以用钩子来写。下面是类的写法。 再来看钩子的写法,也就是函数。 官方推荐使用钩子(函数),而不是类。因为钩子更简洁,代码量少,用起来比较"轻",而类比较"重"。而且,钩子是函数,更符合…
2
关于 cesium 在 micro-app 下无法显示的问题
cesium基座:vite + vue3 子应用:vite + vue3 micro app v1.0.0 rc.29, cesium v1.135 子应用包含一个 cesium map,在基座打开子应用时,cesium 无法显示地图,但是 sence, sky box, model 都能正常显示,唯独地图不显…
3
TypeScript 进阶
TypeScript数组合并了相同类型的对象,而元组(Tuple)合并了不同类型的对象。 元组起源于函数编程语言(如 F ),这些语言中会频繁使用元组。 元组是⼀种特殊的数组类型,可以存储固定数量的元素,并且每个元素的类型是已知的且可以不同。元组⽤于精确描述⼀组值的类型, ? 表示可选元素。 定义一对值分别为 stri…
4
TypeScript 基础
TypeScriptJavaScript 的类型分为两种:原始数据类型(Primitive data types)和对象类型(Object types)。 原始数据类型包括:布尔值、数值、字符串、 null 、 undefined 以及 ES6 中的新类型 Symbol 和 ES10 中的新类型 BigInt 。
5
state
react组件通常需要根据交互更改屏幕上显示的内容。输入表单应该更新输入字段,单击轮播图上的“下一个”应该更改显示的图片,单击“购买”应该将商品放入购物车。组件需要“记住”某些东西:当前输入值、当前图片、购物车。在 React 中,这种组件特有的记忆被称为 state 。
随机文章随机推荐
Profile Image of the Author
Sukksa
记录前端学习与日常
公告
博客刚刚上线,内容还在慢慢补齐。欢迎随便逛逛~
分类
标签
最新动态
站点统计
文章
69
分类
16
标签
17
总字数
178,517
运行时长
0 天
最后活动
0 天前
站点信息
构建平台
Cloudflare Pages
博客版本
Firefly v6.16.8
文章许可
CC BY-NC-SA 4.0
文章目录