首頁  >  文章  >  web前端  >  node.js中模擬require函數與簡單實作機制實例詳解

node.js中模擬require函數與簡單實作機制實例詳解

伊谢尔伦
伊谢尔伦原創
2017-07-24 10:36:311636瀏覽

nodejs中require的載入機制



#1、require的載入檔案順序    

require 載入檔案時可以省略副檔名:

         
require('./module');

     // 此時檔案依JS 檔案執行

#         
require('./module.js');

#js



##n

# // 此時檔案依JSON 檔案解析


         

require('./module.json');

     require('./module.json');

#     // 此時檔案預先設定好的C++ 模組執行


         

require('./module.node');

     // 載入目錄目錄中的package.json

#     // 載入目錄目錄中的目錄.json中main所指的檔案

          require('./module/default.js');

#     // 載入目錄目錄檔案


     通過./ 或../ 開頭:請依照相對路徑從目前檔案所在資料夾開始尋找模組;

        
require('.. /file.js');

=> 上級目錄下找file.js 檔案


#     開始/開始:則以系統根目錄開始尋找模組;


         

require('/Users/iceStone/Documents/file.js'); => 以絕對路徑的方式找出,沒有任何異議
##    如果參數 如果參數參數不以「./「 或」/「 開頭,則表示載入的是一個預設提供的核心模組(位於Node 的系統安裝目錄中):

          require('fs' );

=> 載入核心模組中的檔案系統模組


     或從目前目錄往上搜尋node_modules 目錄中的檔案:


       # ('my_module');

=> 各級node_modules 資料夾中搜尋my_module.js 檔案;

     如果require 傳入的是目錄的路徑,會自動查看該目錄的package.json 文件,然後載入main 欄位指定的入口文件

     如果package.json文件沒有main字段,或根本沒有package.json文件,則預設找目錄下的index.js 文件作為模組:

          require('./calcuator'); => 目前目錄下找calculator 目錄中的index.js 檔案

#=> 目前目錄下找calculator 目錄中的index.js 檔案



##2、require快取


     第一次載入某個模組時,Node 會快取這個模組。以後再載入模組,就直接從快取取出該模組的module.exports 屬性(不會再執行模組)


     如果需要多次執行模組中的程式碼,一般可以讓模組暴露行為(函數),模組的快取可以透過require.cache 拿到,同樣也可以刪除


#3、所有程式碼都運行在模組作用域,不會污染全域作用域。


模擬require函數


require的載入內部比較複雜,下面讓我們進行簡單的模擬載入

####require的簡單實作機制為:############     將傳入的模組id透過載入規則找到對應的模組檔案#########     讀取此檔案裡面的程式碼### ######     通過拼接方式為該段代碼構建私有空間#########     執行該代碼#########     拿到module.exports 返回####### ########
 nodejs_require.js
 // [require函数模拟]

 "use strict"

 function $require(id) {
 //1、先查看模块是否存在,如果不存在则抛出 Can't found file
 //2、如果存在,就读取代码
 const fs = require('fs');
 const path = require('path');

 // 文件名
 let filename = id;
 //查看是否是绝对路径
 if (!path.isAbsolute(filename)) {
  filename = path.join(__dirname, id);
 }

 // 文件目录
 let dirname = path.dirname(filename);

 //模拟require的缓存机制
 $require.cache = $require.cache || {};
 if($require.cache[filename]){
  return $require.cache[filename].exports;
 }

 // 读取模块代码
 let code="";
 try {
  code = fs.readFileSync(filename,'utf-8'); // 阻塞读取文件,不会放入事件队列 
 } catch (error) {
  console.log(" [*]can't found file! ");
  throw error;
 }

 // console.log(code);

 // 3、执行代码,所要执行的代码,需要营造一个独立的空间

 // 定义一个数据容器,用容器去装模块导出的成员
 let _module = { // 每个js模块都会有一个全局的module变量
  id:'.',
  exports:{},
  parent:module,
  filename:filename
 };
 let _exports = _module.exports;

 // 营造一个独立空间
 code = `(function($require,module,_exports,__dirname,__filename){
  $[code]
 })($require,_module,_exports,dirname,filename)`;

 // 执行代码
 eval(code);

 // 缓存
 $require.cache[filename] = _module;
 // 返回结果
 return _module.exports;
 }


 setInterval(()=>{
  const rr = $require("./test.js");
  console.log(rr);
 },1000);
###上面的模組測試使用的兩個模組################
 //test.js
 const date = $require('./date.js');

 console.log(module);

 module.exports = date;

 //date.js
 module.exports = new Date();

以上是node.js中模擬require函數與簡單實作機制實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn