⚡node打怪升级系列 - 浅谈require函数

前言

本文是Node系列require篇

之前学模块化的时候就接触到这个require了,现在重温Node系列,又遇到了这个。

想着,应该有些小伙伴挺感兴趣的,索性就把笔记更新到这里吧~~~

正文开始

1,require是基于CommonJS实现的

工欲善其事必先利其器 ,先了解下CommonJS是什么东西吧

require的实现基于CommonJS规范,属于模块化规范的一种,对模块化规范的发展史有兴趣的小伙伴,# 浅谈模块化,小白看完也能恍然大明白

此处和小伙伴简单聊一下~~~

1.1,模块化是技术不断更迭的产物,核心是解决两个问题

  • 隔离变量:每个模块有其独立作用域

  • 相互通信:模块之间通过modules,modules.exports暴露了入口,可以互相通信

1.2,模块化规范的优点:让复杂项目或者功能的开发变得更简单。

  • 使用网上前辈们开发好的轮子更方便了

  • 可以对复杂项目的开发流程进行碎片化分解,各自为战,提高开发效率和可读性(一个小功能一个页面,读起来可太方便了)(呃~~~也不宜过于碎片化)

1.3,模块化的发展史

1,作用域让变量隔离:bar的作用域只限于foo函数之中,外面是访问不到的

js 复制代码
function foo() {
    var bar = 1;
    var baz = 2;
}

2,访问函数里的变量:obj.a可以访问到resolve函数中过的bar了

js 复制代码
var obj = {
    a: {

    }
};

function resolve(a) {
    var bar = 1;
    var baz = 2;
    a = {
        bar, baz
    }
}

resolve(obj.a)

3,CommonJS规范雏形出来了

js 复制代码
var module = {
    exports: {

    }
};

function resolve(module, exports) {
    var bar = 1;
    var baz = 2;
    module.exports = {
        bar, baz
    }
}

resolve(module, module.exports)

踩坑:上面的第10行使用module.exports而不直接用exports的原因是为了保持引用关系不被打破。

2,require函数的简易实现

index.js

js 复制代码
console.log('hello world')

require.js

js 复制代码
// const xxx = require('xxx.js')

const { readFileSync } = require("fs");
const { resolve } = require("path");
const { Script } = require("vm");

function my_require(filename) {
  const fileContent = readFileSync(resolve(__dirname, filename), 'utf-8');
  const warpped = `(function(require, module, exports) {
        ${fileContent}
    })`

  const scripts = new Script(warpped, {
    filename: 'index.js',
  })

  const module = {
    exports: {}
  }

  const func = scripts.runInThisContext();

  func(my_require, module, module.exports);

  return module.exports;

}

global.my_require = my_require;

my_require('./index.js');

2.1,核心点解析

1,代码中的fspathvmnode这个宿主环境提供的API,可以直接使用。

  • fs path: 操作磁盘

  • vm: Node.js 的虚拟机模块,它提供了一种在 V8 虚拟机环境中执行 JavaScript 代码的机制。

这个宿主环境,小伙伴们可以类比浏览器,比如chrome浏览器也是一个宿主环境,它提供了document, window等Api可以操作DOM等功能

关于node的相关知识点,我会另开一篇文章,到时候会贴到这里 => 占位

2,readFileSync

fs模块提供的方法,用于读取文件内容

readFileSync(resolve(文件路径, 文件名), 确定编码格式输出文件内容);

3,warpped打印出来的内容如下图:

4,第13-15行:new Script

创建一个叫index.js的脚步文件对象,脚本对象包含了 warpped 中的代码。此处的index.js可不写,可随便起名

5,第21行:runInThisContext

vm 模块提供的方法,用于在当前的上下文中运行之前创建的脚本文件,生成一个fun函数(此时,fuc函数还没被执行)

第4小点 + 第5小点等于是定义了一个func函数,函数体就是上面warpped打印的内容

6,为什么9-11行不能写成下面这样呢?

js 复制代码
const warpped = `function(require, module, exports) { ${fileContent} }`

原因如下图:

上文有说scripts.runInThisContext()会运行一遍创建好的脚本文件

  • 立即执行函数体(上图蓝框)运行后会变成普通函数体。
  • 普通函数体(上图黄框)运行后就会报错

完结

这篇文章我尽力把我的笔记和想法放到这了,希望对小伙伴有帮助。

欢迎转载,但请注明来源。

最后,希望小伙伴们给我个免费的点赞,祝大家心想事成,平安喜乐。

相关推荐
DK七七3 分钟前
多端校园圈子论坛小程序,多个学校同时代理,校园小程序分展示后台管理源码
开发语言·前端·微信小程序·小程序·php
老赵的博客13 分钟前
QSS 设置bug
前端·bug·音视频
Chikaoya14 分钟前
项目中用户数据获取遇到bug
前端·typescript·vue·bug
南城夏季15 分钟前
蓝领招聘二期笔记
前端·javascript·笔记
Huazie15 分钟前
来花个几分钟,轻松掌握 Hexo Diversity 主题配置内容
前端·javascript·hexo
NoloveisGod40 分钟前
Vue的基础使用
前端·javascript·vue.js
GISer_Jing42 分钟前
前端系统设计面试题(二)Javascript\Vue
前端·javascript·vue.js
海上彼尚1 小时前
实现3D热力图
前端·javascript·3d
杨过姑父1 小时前
org.springframework.context.support.ApplicationListenerDetector 详细介绍
java·前端·spring
理想不理想v1 小时前
使用JS实现文件流转换excel?
java·前端·javascript·css·vue.js·spring·面试