国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

require源碼閱讀

Batkid / 2507人閱讀

require gitlab

mudule對象化

require最終會把每個模塊都轉化為對象

function Module(id, parent) {
    this.id = id;
    this.exports = {};
    this.parent = parent;
    updateChildren(parent, this, false);
    this.filename = null;
    this.loaded = false;
    this.children = [];
}
require方法

用assert斷言輸入的合法性并調用_load方法還有一個調用_load的是

Module.runMain = function() {
    // Load the main module--the command line argument.
    Module._load(process.argv[1], null, true);
    // Handle any nextTicks added in the first tick of the program
    process._tickCallback();
};

這個我不是特別確定,但基本確定是給node xxx.js 這條命令調用的

load方法

這里有很多是關于處理main的,核心的一段是

if (isMain) {
    process.mainModule = module;
    module.id = ".";
}

這個佐證了上面runMain是給node xxx.js 這條命令調用的這個論點,另外main模塊的id一定是 ".",并且parent一定是空。
另外在調用前會先查找模塊緩存的是否存在。
以下代碼為了簡化刪去main模塊的處理

//創建沒有原型的空對象
Module._cache = Object.create(null);
Module._pathCache = Object.create(null);

Module._load = function(request, parent, isMain) {
  if (parent) {
    debug("Module._load REQUEST %s parent: %s", request, parent.id);
  }

  var filename = Module._resolveFilename(request, parent, isMain);

//緩存中是否存在
  var cachedModule = Module._cache[filename];
  if (cachedModule) {
    updateChildren(parent, cachedModule, true);
    return cachedModule.exports;
  }

//是否是native模塊
  if (NativeModule.nonInternalExists(filename)) {
    debug("load native module %s", request);
    return NativeModule.require(filename);
  }

//其他模塊處理
  var module = new Module(filename, parent);

  Module._cache[filename] = module;

  tryModuleLoad(module, filename);

  return module.exports;
};

這個部分說明了加載模塊首先是判斷模塊名,之后是查找緩存,查找native 模塊,然后是其他模塊,最后的return是最為關鍵的,返回值永遠是module的 exports

查找node_modules文件夾的規則
 Module._nodeModulePaths = function(from) {
    // guarantee that "from" is absolute.
    from = path.resolve(from);
    // Return early not only to avoid unnecessary work, but to *avoid* returning
    // an array of two items for a root: [ "http://node_modules", "/node_modules" ]
    if (from === "/")
      return ["/node_modules"];

    // note: this approach *only* works when the path is guaranteed
    // to be absolute.  Doing a fully-edge-case-correct path.split
    // that works on both Windows and Posix is non-trivial.
    const paths = [];
    var p = 0;
    var last = from.length;
    for (var i = from.length - 1; i >= 0; --i) {
      const code = from.charCodeAt(i);
      if (code === 47//*/*/) {
        if (p !== nmLen)
          paths.push(from.slice(0, last) + "/node_modules");
        last = i;
        p = 0;
      } else if (p !== -1) {
        if (nmChars[p] === code) {
          ++p;
        } else {
          p = -1;
        }
      }
    }

從from開始逐層向上查找node_modules文件夾

Module._extensions

js,json,node,mjs
每個后綴的文件都有對應的打開方式
js 清除可能的BOM頭后加載
json json Parse
node .node 這是C/C++編寫的擴展文件,通過dlopen()方法加載最后編譯生成的文件,可以當作是一個系統調用

findPath

這部分代碼比較多,只看一段注釋即可
// given a module name, and a list of paths to test, returns the first
// matching file in the following precedence.
//
// require("a.")
// -> a.
//
// require("a")
// -> a
// -> a.
// -> a/index.

package.json

node會去尋找路徑中的package.json文件并且會加載其中的main,并放入packagecache中,用main中指定的文件再去確認絕對路徑然后加載

function readPackage(requestPath) {
  const entry = packageMainCache[requestPath];
  if (entry)
    return entry;

  const jsonPath = path.resolve(requestPath, "package.json");
  const json = internalModuleReadFile(path.toNamespacedPath(jsonPath));

  if (json === undefined) {
    return false;
  }

  try {
    var pkg = packageMainCache[requestPath] = JSON.parse(json).main;
  } catch (e) {
    e.path = jsonPath;
    e.message = "Error parsing " + jsonPath + ": " + e.message;
    throw e;
  }
  return pkg;
}
compile

如何查找到的文件基本清楚了,之后就是最常用的js的compile了
js模塊的外層一定會被套上

Module.wrapper = [
  "(function (exports, require, module, __filename, __dirname) { ",
  "
});"
];

之后涉及了斷點的處理,是在vm模塊中的Srcript對象中的runInThisContext

后面有一句說明了為什么node中的所有文件也可以擁有Module的各種方法和特性 require 包括那些并不是main的文件,另外所有的模塊也是公用的模塊緩存,利用Module require中的return Module._load(path, this, /* isMain */ false);把自己的this作為parent作為Module對象的parent
var require = internalModule.makeRequireFunction(this);
makeRequireFunction的代碼

// Invoke with makeRequireFunction(module) where |module| is the Module object
// to use as the context for the require() function.
function makeRequireFunction(mod) {
  const Module = mod.constructor;

  function require(path) {
    try {
      exports.requireDepth += 1;
      return mod.require(path);
    } finally {
      exports.requireDepth -= 1;
    }
  }

  function resolve(request, options) {
    return Module._resolveFilename(request, mod, false, options);
  }

  require.resolve = resolve;

  function paths(request) {
    return Module._resolveLookupPaths(request, mod, true);
  }

  resolve.paths = paths;

  require.main = process.mainModule;

  // Enable support to add extra extension types.
  require.extensions = Module._extensions;

  require.cache = Module._cache;

  return require;
}

執行compiledWrapper,對應wrapper插入的js
result = compiledWrapper.call(this.exports, this.exports, require, this, filename, dirname);
首先是compiledWrapper的this綁定在了Module自己exports上,自己的exports也作為了參數被注入,相當于隱式的賦值exports就是compiledWrapper中的exports了這個就成了對外唯一的輸出了,其他的所有值都成了compiledWrapper的私有不會污染全局,require作為參數被注入,另外就是文件名 和路徑的注入

從上述處理加載的過程我們可以發現只要有require node就會繼續加載,另外CommonJs同步的特點也是在這體現出來的

對照學習

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/93763.html

相關文章

  • koa源碼閱讀之目錄結構與輔助庫相關

    摘要:從一個對象里面提取需要的屬性這篇文章一直想寫了還想起那一夜我看到白天的代碼,實在太美了。 koa源碼lib主要文件有 application.js context.js request.js response.js application.js koa主要的邏輯處理代碼整個koa的處理 context.js 將req,res方法 掛載在這,生成ctx上下文對象 requests....

    sherlock221 評論0 收藏0
  • 閱讀sea.js源碼小結

    摘要:依賴信息是一個數組,比如上面的依賴數組是源碼如下是利用正則解析依賴的一個函數時間出發函數主要看這個部分注釋是防止拷貝該時間的回調函數,防止修改,困惑了一下。對的賦值需要同步執行,不能放在回調函數里。 sea.js想解決的問題 惱人的命名沖突 煩瑣的文件依賴 對應帶來的好處 Sea.js 帶來的兩大好處: 通過 exports 暴露接口。這意味著不需要命名空間了,更不需要全局變量。...

    chavesgu 評論0 收藏0
  • 一步步去閱讀koa源碼,整體架構分析

    摘要:閱讀好的框架的源碼有很多好處,從大神的視角去理解整個框架的設計思想。使用其實某個框架閱讀源碼的時候,首先我們要會去用這個框架,因為用了我們才知道,某個是怎么用,哪里有坑,哪里設計的精妙。 閱讀好的框架的源碼有很多好處,從大神的視角去理解整個框架的設計思想。大到架構設計,小到可取的命名風格,還有設計模式、實現某類功能使用到的數據結構和算法等等。 使用koa 其實某個框架閱讀源碼的時候,首...

    haoguo 評論0 收藏0
  • 一步步去閱讀koa源碼,整體架構分析

    摘要:閱讀好的框架的源碼有很多好處,從大神的視角去理解整個框架的設計思想。使用其實某個框架閱讀源碼的時候,首先我們要會去用這個框架,因為用了我們才知道,某個是怎么用,哪里有坑,哪里設計的精妙。 閱讀好的框架的源碼有很多好處,從大神的視角去理解整個框架的設計思想。大到架構設計,小到可取的命名風格,還有設計模式、實現某類功能使用到的數據結構和算法等等。 使用koa 其實某個框架閱讀源碼的時候,首...

    chaos_G 評論0 收藏0
  • Koa源碼閱讀筆記(2) -- compose

    摘要:于是抱著知其然也要知其所以然的想法,開始閱讀的源代碼。問題讀源代碼時,自然是帶著諸多問題的。源代碼如下在被處理完后,每當有新請求,便會調用,去處理請求。接下來會繼續寫一些閱讀筆記,因為看的源代碼確實是獲益匪淺。 本筆記共四篇Koa源碼閱讀筆記(1) -- coKoa源碼閱讀筆記(2) -- composeKoa源碼閱讀筆記(3) -- 服務器の啟動與請求處理Koa源碼閱讀筆記(4) -...

    roland_reed 評論0 收藏0

發表評論

0條評論

Batkid

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<