node.js 包管理及模块-node.js 一

node.js 原理剖析
模块化概述

js 不是模块化编程语言,它不支持class
es6发布后 可以方便在js中使用类和模块了
-> 模块化规范
浏览器端规范
AMD(require.js)遵循的AMD规范(同步执行)
CMD(Sea.js) 遵循的CMD规范
ES6
服务器端规范
CommonJS(Node.js是CommonJS的实现)
Node的应用是由模块组成的
CommonJS特点
所有代码运行在当前模块作用域,不会污染全局作用域
模块同步加载,根据代码执行顺序载入
模块可多次加载,只会在第一次加载的时候运行一次,运行结果被缓存
以后再次加载模块,会直接从缓存中读取数据
module对象详解

module001.js
let name = 'eval'
let getName = function (name) {
console.log(name);
}
// 模块导出,暴露在外面
module.exports = {
name: name,
getName: getName,
}
person.js
// 引入 module001.js
let person = require('./module001.js')
console.log(person)

// 终端中当前目录执行node person.js
person.getName('study163')
// 修改name的值
person.name = 'updateName'
console.log(person)
// 终端中当前目录执行node person.js
模块分类 
module对象的属性
id: 当前模块的id 唯一的;
exports: 表示当前模块暴露给外部的值。
parent: 是一个对象,表示调用当前模块的模块。
children: 是一个对象,表示当前模块调用的模块。
filename: 模块的绝对路径。
paths: 从当前模块开始查找node_modules目录,然后依次进入到父目录,查找父目录下的node_modules目录;依次换代,直到根目录下的node_modules目录。
loaded: 一个布尔值,表示当前模块是否完全加载。
一直找,直到找到根目录
03module.js
// 直接导出一个对象
module.exports = {
name: 'evan',
getName: function (name) {
console.log(name)
}
}
console.log(module)

核心模块
Node.js提供的模块,例如http模块,fs模块等,
核心模块 -----通过编译------二进制文件----node启动时部分核心加载到内存中,因此部分模块不需要手动加载,加载的比较快;
文件模块
自己编辑的模块;文件模块是按需加载,加载比较慢。
module.exports 与exports

都是引用类型变量,指向同一个内存地址,在node中开始都指向空对象
exports 通过形参的方式传入,直接赋值给形参引用,不能改变作用域外的值
module.exports就是为了角色exports直接赋值的问题而产生的
04.module.exports
var module = {
exports: {}
}
var exports = module.exports;
function change(exports) {
// 通过形参的方式传入的exports
exports.name = 'evan';
// 下面的直接赋值是错误的,exports的作用域只有这个作用域中,如果这样赋值的话,exports指向的地址(重新指向的新的地址)和module.exports的指向地址就不一样了。
exports = {

age: 18;
}
console.log(exports);
}
change(exports)

console.log(module.exports)
而module.exports 是可以直接赋值的,因为它是外部传进来,而exports则不可以。
正确写法如下:
let name = 'ab';
let text = 'cd';
module.exports = {
name, text
};
require方法详解

require方法传入的是模块标识符

路径分析 -> 文件定位 -> 编译执行

路径分析(模块标识符分析)
1.核心模块。
2. 以'.'或者'../'开始的相对路径文件模块,如果找不到在modules中找,不利于项目迁移。
3. 以'/'开始的绝对路径模块。
非路径形式的模块(直接字符串)

文件定位

扩展名分析 .js 、.node文件去找或java扩展
目标文件和包分析
o5-load.js
找课程资料查询
// 计算绝对路径 
...
// 第一步 如果有缓存,取出缓存。
...
// 第二步 是否为内置模块。
...
// 第三步 生成模块实例,存入缓存(如果上面两步都没有找到,创建)
...
// 第四步 加载模块
...
// 第五步 输出模块的exports属性
...

查询路径js 找课程资料查询,一个模块必须有个package.json 和入口文件 index.js
// 列出所有可能的后缀名: .js 、 .json 、.node
// 如果是绝对路径就不再搜索
// 是否有后缀的目录斜杠
// 第一步 如果当前路径已经缓存中,就直接返回缓存
// 第二步 遍历所有路径
// 第三步 是否存在该模块文件
// 第四步 该模块文件加载后缀名,是否存在
// 第五步 目录中是否存在package.json
// 第六步 是否存在目录名+ index + 后缀名
// 第七步 将找到的文件路径存入返回缓存,然后返回
// 第八步 提示文件不存在

// npm init 创建package.json 如果目录没有main字段且也没有index.js的话,就提示你什么也没有找到
// node 运行js node .js文件
var a = require('./module001.js')
var b = require('./module001.js')
console.log(a===b) true

// 因为导出module.exports 多个同一个内容的话,第二次导出会读取缓存,所以是指向同一块地址

node.js 原理剖析

自定义模块和核心模块相同时,自定义模块加载失败

require方法详解

原文地址:https://www.cnblogs.com/TheYouth/p/13953336.html