自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

給大家變個(gè) Node.js 的小魔術(shù)

開(kāi)發(fā) 前端
Node.js 的 js 模塊加載的流程是 load -> _extensions['.js'] -> _compile,可以通過(guò)修改 _extensions['.js'] 來(lái)達(dá)到 hook 的目的,比如在 _compile 之前做一些代碼轉(zhuǎn)換。

[[425926]]

本文轉(zhuǎn)載自微信公眾號(hào)「神光的編程秘籍」,作者神說(shuō)要有光。轉(zhuǎn)載本文請(qǐng)聯(lián)系神光的編程秘籍公眾號(hào)。

魔術(shù)演出

我們準(zhǔn)備一個(gè) Node.js 的模塊 input.js:

  1. // input.js 
  2. function func() { 
  3.     return '卡頌' 
  4. module.exports = func(); 

這個(gè)模塊返回的值是啥?

東東:是“卡頌”。

那我在另一個(gè)模塊 test.js 中引入這個(gè) input.js,然后打印一下:

  1. // test.js 
  2. const data = require('./input.js'); 
  3. console.log(data); 

之后我在 entry.js 里面引入 test.js:

  1. require('./test.js'); 

執(zhí)行之后打印的是啥?

東東:是“卡頌”。

真的么?那我們跑一下:

打印的是啥:

東東:是 “卡帥”,哇,好神奇,怎么做到的。

我:想不想學(xué)?

東東:想。

我:那接下來(lái)就進(jìn)入魔術(shù)揭秘時(shí)間。

魔術(shù)揭秘

Node.js 加載模塊的流程是這樣的:

模塊加載會(huì)調(diào)用 load 方法, load 會(huì)調(diào)用對(duì)應(yīng)后綴名的 _extensions 的方法來(lái)處理,其中會(huì)調(diào)用 _compile 來(lái)編譯并把結(jié)果放入 cache,之后返回。

所以呢?我們想改變 js 模塊的返回值,只需要改造下 Module._extensions['.js'] 就可以了。

  1. const Module = require('module'); 
  2. const fs = require('fs'); 
  3.  
  4. Module._extensions['.js'] = function (module, filename) { 
  5.     let content = fs.readFileSync(filename, 'utf8'); 
  6.     if (filename.includes('input')) { 
  7.         content = content.replace('卡頌''卡帥'); 
  8.     } 
  9.     module._compile(content, filename); 
  10. }; 

我們對(duì) filename 為 input 的文件,讀取內(nèi)容之后進(jìn)行了替換,之后再調(diào)用 module._compile 來(lái)編譯,后續(xù)流程不變。

模塊引入方式不變,但是模塊內(nèi)容已經(jīng)悄悄的被修改了,這個(gè)魔術(shù)的名字叫做 require hook。

東東:原來(lái)是你藏了一段代碼沒(méi)展示。

我:魔術(shù)都是這樣的啊。而且你別小看了這個(gè) require hook,它能做到很多強(qiáng)大的功能呢。

東東:哦?比如說(shuō)

我:比如說(shuō) ts-node,它是怎么做到直接 require ts 模塊的?就是通過(guò) require hook 偷偷做了編譯,其實(shí)你執(zhí)行的是編譯后的 js。

比如說(shuō) babel-register 它是怎么做到直接執(zhí)行帶有 esnext 新特性的代碼的?也是通過(guò) require hook 偷偷做了編譯。

還有覆蓋率測(cè)試,其實(shí)是通過(guò)函數(shù)插樁做到的,也就是你每執(zhí)行一條語(yǔ)句都會(huì)計(jì)數(shù)。怎么插樁呢?跑單測(cè)的時(shí)候也沒(méi)手動(dòng)插樁啊,就是因?yàn)楣ぞ邇?nèi)部偷偷通過(guò) require hook 做了插樁,才能得到覆蓋率數(shù)據(jù)。

東東:這個(gè)魔術(shù)還挺有用的嘛。學(xué)會(huì)了~

總結(jié)

Node.js 的 js 模塊加載的流程是 load -> _extensions['.js'] -> _compile,可以通過(guò)修改 _extensions['.js'] 來(lái)達(dá)到 hook 的目的,比如在 _compile 之前做一些代碼轉(zhuǎn)換。

這種 hook 在 babel-register、ts-node 還有單測(cè)的覆蓋率測(cè)試中都有應(yīng)用,能夠達(dá)到透明的修改代碼的目的。

因?yàn)殚_(kāi)發(fā)者不知道代碼什么時(shí)候被修改的,所以看起來(lái)比較神奇。

 

責(zé)任編輯:武曉燕 來(lái)源: 神光的編程秘籍
相關(guān)推薦

2022-03-30 08:36:32

Node.jsPRHTTP

2013-11-01 09:34:56

Node.js技術(shù)

2015-03-10 10:59:18

Node.js開(kāi)發(fā)指南基礎(chǔ)介紹

2020-05-29 15:33:28

Node.js框架JavaScript

2021-12-25 22:29:57

Node.js 微任務(wù)處理事件循環(huán)

2012-02-03 09:25:39

Node.js

2011-09-09 14:23:13

Node.js

2011-11-01 10:30:36

Node.js

2011-09-08 13:46:14

node.js

2011-09-02 14:47:48

Node

2012-10-24 14:56:30

IBMdw

2011-11-10 08:55:00

Node.js

2021-01-04 08:09:58

Node.js磁盤(pán)接口

2011-11-02 09:04:15

Node.js

2021-09-26 05:06:04

Node.js模塊機(jī)制

2021-11-06 18:40:27

js底層模塊

2019-07-09 14:50:15

Node.js前端工具

2015-06-23 15:27:53

HproseNode.js

2021-04-06 10:15:29

Node.jsHooks前端

2020-10-26 08:34:13

Node.jsCORS前端
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)