Node.js v21.7.2 文件
- Node.js v21.7.2
- ► 目錄
-
► 索引
- 斷言測試
- 非同步背景追蹤
- 非同步掛鉤
- 緩衝區
- C++ 外掛程式
- 使用 Node-API 的 C/C++ 外掛程式
- C++ 嵌入式 API
- 子程序
- 叢集
- 命令列選項
- 主控台
- Corepack
- 加密
- 偵錯器
- 已棄用的 API
- 診斷頻道
- DNS
- 網域
- 錯誤
- 事件
- 檔案系統
- 全域變數
- HTTP
- HTTP/2
- HTTPS
- 檢查器
- 國際化
- 模組:CommonJS 模組
- 模組:ECMAScript 模組
- 模組:
node:module
API - 模組:套件
- 網路
- 作業系統
- 路徑
- 效能掛鉤
- 權限
- 程序
- Punycode
- 查詢字串
- Readline
- REPL
- 報告
- 單一可執行應用程式
- 串流
- 字串解碼器
- 測試執行器
- 計時器
- TLS/SSL
- 追蹤事件
- TTY
- UDP/資料包
- URL
- 公用程式
- V8
- VM
- WASI
- Web Crypto API
- Web Streams API
- 工作執行緒
- Zlib
- ► 其他版本
- ► 選項
REPL#
原始碼: lib/repl.js
node:repl
模組提供 Read-Eval-Print-Loop (REPL) 實作,可用作獨立程式或包含在其他應用程式中。可使用以下方式存取:
const repl = require('node:repl');
設計和功能#
node:repl
模組匯出 repl.REPLServer
類別。執行時,repl.REPLServer
個體會接受個別使用者輸入行,根據使用者定義的評估函數評估這些行,然後輸出結果。輸入和輸出分別來自 stdin
和 stdout
,或可能連接到任何 Node.js 串流。
repl.REPLServer
的實例支援自動完成輸入、完成預覽、簡化的 Emacs 風格列編輯、多行輸入、ZSH 風格的反向 i 搜尋、ZSH 風格的子字串為基礎的歷程搜尋、ANSI 風格輸出、儲存和還原目前的 REPL 會話狀態、錯誤復原和可自訂的評估函式。不支援 ANSI 風格和 Emacs 風格列編輯的終端機,會自動改用有限的功能組。
指令和特殊鍵#
所有 REPL 實例都支援下列特殊指令
.break
:在輸入多行表達式的過程中,輸入.break
指令(或按 Ctrl+C)以中止輸入或處理該表達式。.clear
:將 REPLcontext
重設為空物件,並清除正在輸入的任何多行表達式。.exit
:關閉 I/O 串流,導致 REPL 退出。.help
:顯示這份特殊指令清單。.save
:將目前的 REPL 會話儲存到檔案:> .save ./file/to/save.js
.load
:將檔案載入目前的 REPL 會話。> .load ./file/to/load.js
.editor
:進入編輯器模式(按 Ctrl+D 結束,按 Ctrl+C 取消)。
> .editor
// Entering editor mode (^D to finish, ^C to cancel)
function welcome(name) {
return `Hello ${name}!`;
}
welcome('Node.js User');
// ^D
'Hello Node.js User!'
>
REPL 中的下列按鍵組合具有下列特殊效果
- Ctrl+C:按一次時,效果與
.break
指令相同。在空白行按兩次時,效果與.exit
指令相同。 - Ctrl+D:效果與
.exit
指令相同。 - Tab:在空白行按時,顯示全域和區域(範圍)變數。在輸入其他輸入時按時,顯示相關的自動完成選項。
有關反向 i 搜尋相關的按鍵繫結,請參閱 reverse-i-search
。有關所有其他按鍵繫結,請參閱 TTY 按鍵繫結。
預設評估#
預設情況下,repl.REPLServer
的所有執行個體都會使用評估 JavaScript 表達式並提供存取 Node.js 內建模組的評估函式。建立 repl.REPLServer
執行個體時,傳入替代評估函式可以覆寫此預設行為。
JavaScript 表達式#
預設評估器支援直接評估 JavaScript 表達式
> 1 + 1
2
> const m = 2
undefined
> m + 1
3
除非在區塊或函式內另有範圍,否則使用 const
、let
或 var
關鍵字隱式宣告或宣告的變數會在全域範圍內宣告。
全域和區域範圍#
預設評估器提供存取全域範圍內存在的任何變數。透過將變數指定給與每個 REPLServer
關聯的 context
物件,可以明確地將變數公開至 REPL
const repl = require('node:repl');
const msg = 'message';
repl.start('> ').context.m = msg;
context
物件中的屬性會顯示為 REPL 內的區域
$ node repl_test.js
> m
'message'
預設情況下,context 屬性並非唯讀。若要指定唯讀全域變數,必須使用 Object.defineProperty()
定義 context 屬性
const repl = require('node:repl');
const msg = 'message';
const r = repl.start('> ');
Object.defineProperty(r.context, 'm', {
configurable: false,
enumerable: true,
value: msg,
});
存取核心 Node.js 模組#
預設評估器會在使用時自動將 Node.js 核心模組載入 REPL 環境。例如,除非另行宣告為全域或範圍變數,否則輸入 fs
會根據要求評估為 global.fs = require('node:fs')
。
> fs.createReadStream('./some/file');
全域未捕獲例外#
REPL 使用 domain
模組來捕捉那個 REPL 會話的所有未捕捉例外。
REPL 中 domain
模組的這種使用具有以下副作用
-
未捕捉例外僅在獨立 REPL 中發出
'uncaughtException'
事件。在另一個 Node.js 程式中 REPL 中新增這個事件的監聽器會導致ERR_INVALID_REPL_INPUT
。const r = repl.start(); r.write('process.on("uncaughtException", () => console.log("Foobar"));\n'); // Output stream includes: // TypeError [ERR_INVALID_REPL_INPUT]: Listeners for `uncaughtException` // cannot be used in the REPL r.close();
-
嘗試使用
process.setUncaughtExceptionCaptureCallback()
會擲回ERR_DOMAIN_CANNOT_SET_UNCAUGHT_EXCEPTION_CAPTURE
錯誤。
_
(底線) 變數的指定#
預設評估器會預設將最新評估的表達式結果指定給特殊變數 _
(底線)。明確設定 _
為值會停用此行為。
> [ 'a', 'b', 'c' ]
[ 'a', 'b', 'c' ]
> _.length
3
> _ += 1
Expression assignment to _ now disabled.
4
> 1 + 1
2
> _
4
類似地,如果有的話,_error
會參考最後看到的錯誤。明確設定 _error
為值會停用此行為。
> throw new Error('foo');
Uncaught Error: foo
> _error.message
'foo'
await
關鍵字#
在頂層啟用對 await
關鍵字的支援。
> await Promise.resolve(123)
123
> await Promise.reject(new Error('REPL await'))
Uncaught Error: REPL await
at REPL2:1:54
> const timeout = util.promisify(setTimeout);
undefined
> const old = Date.now(); await timeout(1000); console.log(Date.now() - old);
1002
undefined
在 REPL 中使用 await
關鍵字的一個已知限制是它會使 const
和 let
關鍵字的詞彙範圍無效。
例如
> const m = await Promise.resolve(123)
undefined
> m
123
> const m = await Promise.resolve(234)
undefined
> m
234
--no-experimental-repl-await
將停用 REPL 中的頂層 await。
反向 i 搜尋#
REPL 支援雙向反向 i 搜尋,類似於 ZSH。使用 Ctrl+R 向後搜尋,Ctrl+S 向前搜尋。
重複的記錄會被略過。
只要按下任何不對應於反向搜尋的按鍵,就會接受輸入。可以按 Esc 或 Ctrl+C 取消。
立即變更方向會從目前位置起,搜尋預期方向的下一筆輸入。
自訂評估函式#
建立新的 repl.REPLServer
時,可以提供自訂評估函式。例如,這可以用於實作完全自訂的 REPL 應用程式。
以下說明一個假設範例,說明 REPL 如何將文字從一種語言翻譯成另一種語言
const repl = require('node:repl');
const { Translator } = require('translator');
const myTranslator = new Translator('en', 'fr');
function myEval(cmd, context, filename, callback) {
callback(null, myTranslator.translate(cmd));
}
repl.start({ prompt: '> ', eval: myEval });
可復原錯誤#
在 REPL 提示字元按 Enter 會將目前的輸入行傳送至 eval
函式。為了支援多行輸入,eval
函式可以傳回 repl.Recoverable
的執行個體至提供的回呼函式
function myEval(cmd, context, filename, callback) {
let result;
try {
result = vm.runInThisContext(cmd);
} catch (e) {
if (isRecoverableError(e)) {
return callback(new repl.Recoverable(e));
}
}
callback(null, result);
}
function isRecoverableError(error) {
if (error.name === 'SyntaxError') {
return /^(Unexpected end of input|Unexpected token)/.test(error.message);
}
return false;
}
自訂 REPL 輸出#
預設情況下,repl.REPLServer
執行個體會在將輸出寫入提供的 Writable
串流(預設為 process.stdout
)之前,使用 util.inspect()
方法來格式化輸出。預設情況下,showProxy
檢查選項設為 true,而 colors
選項則會根據 REPL 的 useColors
選項設為 true。
可以在建構時指定 useColors
布林值選項,以指示預設寫入器使用 ANSI 樣式代碼來為 util.inspect()
方法輸出的內容加上色彩。
如果 REPL 是以獨立程式執行,也可以使用反映 util.inspect()
的 defaultOptions
的 inspect.replDefaults
屬性,在 REPL 內部變更 REPL 的 檢查預設值。
> util.inspect.replDefaults.compact = false;
false
> [1]
[
1
]
>
若要完全自訂 repl.REPLServer
執行個體的輸出,請在建構時為 writer
選項傳入一個新的函式。例如,下列範例會將任何輸入文字轉換成大寫
const repl = require('node:repl');
const r = repl.start({ prompt: '> ', eval: myEval, writer: myWriter });
function myEval(cmd, context, filename, callback) {
callback(null, cmd);
}
function myWriter(output) {
return output.toUpperCase();
}
類別:REPLServer
#
options
<Object> | <string> 請參閱repl.start()
- 延伸:<readline.Interface>
repl.REPLServer
的執行個體是使用 repl.start()
方法或直接使用 JavaScript new
關鍵字來建立的。
const repl = require('node:repl');
const options = { useColors: true };
const firstInstance = repl.start(options);
const secondInstance = new repl.REPLServer(options);
事件:'exit'
#
當 REPL 退出時,會發出 'exit'
事件,退出方式包括接收 .exit
命令作為輸入、使用者按兩次 Ctrl+C 以發出 SIGINT
,或按 Ctrl+D 以在輸入串流上發出 'end'
。偵聽器回呼會在沒有任何引數的情況下呼叫。
replServer.on('exit', () => {
console.log('Received "exit" event from repl!');
process.exit();
});
事件:'reset'
#
當 REPL 的內容重設時,會發出 'reset'
事件。這會在收到 .clear
指令作為輸入時發生,除非 REPL 使用預設評估器,且 repl.REPLServer
執行個體已使用設定為 true
的 useGlobal
選項建立。監聽器回呼函式會呼叫參照 context
物件,作為唯一的引數。
這主要可用於將 REPL 內容重新初始化為某些預先定義的狀態
const repl = require('node:repl');
function initializeContext(context) {
context.m = 'test';
}
const r = repl.start({ prompt: '> ' });
initializeContext(r.context);
r.on('reset', initializeContext);
執行此程式碼時,可以修改全域 'm'
變數,但接著使用 .clear
指令將其重設為其初始值
$ ./node example.js
> m
'test'
> m = 1
1
> m
1
> .clear
Clearing context...
> m
'test'
>
replServer.defineCommand(keyword, cmd)
#
keyword
<string> 指令關鍵字(沒有開頭的.
字元)。cmd
<Object> | <Function> 處理指令時要呼叫的函式。
replServer.defineCommand()
方法用於將新的 .
開頭指令新增至 REPL 執行個體。此類指令會透過輸入 .
後接 keyword
來呼叫。cmd
是 Function
或具有下列屬性的 Object
help
<string> 輸入.help
時要顯示的說明文字(選用)。action
<Function> 要執行的函式,可選擇接受單一字串引數。
下列範例顯示新增至 REPL 執行個體的兩個新指令
const repl = require('node:repl');
const replServer = repl.start({ prompt: '> ' });
replServer.defineCommand('sayhello', {
help: 'Say hello',
action(name) {
this.clearBufferedCommand();
console.log(`Hello, ${name}!`);
this.displayPrompt();
},
});
replServer.defineCommand('saybye', function saybye() {
console.log('Goodbye!');
this.close();
});
新的指令可以從 REPL 執行個體內部使用
> .sayhello Node.js User
Hello, Node.js User!
> .saybye
Goodbye!
replServer.displayPrompt([preserveCursor])
#
preserveCursor
<boolean>
replServer.displayPrompt()
方法準備 REPL 執行個體以接受使用者的輸入,將設定的 prompt
列印到 output
中的新行,並繼續 input
以接受新的輸入。
當輸入多行時,會列印省略號,而不是「提示」。
當 preserveCursor
為 true
時,游標位置不會重設為 0
。
replServer.displayPrompt
方法主要用於從使用 replServer.defineCommand()
方法註冊的指令的動作函數中呼叫。
replServer.clearBufferedCommand()
#
replServer.clearBufferedCommand()
方法會清除已暫存但尚未執行的任何指令。此方法主要用於從使用 replServer.defineCommand()
方法註冊的指令的動作函數中呼叫。
replServer.parseREPLKeyword(keyword[, rest])
#
一個內部方法用於解析和執行 REPLServer
關鍵字。如果 keyword
是有效的關鍵字,傳回 true
,否則傳回 false
。
replServer.setupHistory(historyPath, callback)
#
historyPath
<string> 歷史記錄檔案路徑callback
<Function> 當歷史記錄寫入準備就緒或發生錯誤時呼叫err
<Error>repl
<repl.REPLServer>
初始化 REPL 執行個體的歷史記錄檔案。在執行 Node.js 二進位檔並使用命令列 REPL 時,預設會初始化一個歷史記錄檔案。然而,在以程式設計方式建立 REPL 時並非如此。在以程式設計方式處理 REPL 執行個體時,請使用此方法初始化歷史記錄檔案。
repl.builtinModules
#
所有 Node.js 模組名稱的清單,例如 'http'
。
repl.start([options])
#
options
<Object> | <string>prompt
<string> 要顯示的輸入提示。預設:'> '
(含尾隨空白)。input
<stream.Readable> REPL 輸入將從中讀取的Readable
串流。預設:process.stdin
。output
<stream.Writable> REPL 輸出將寫入其中的Writable
串流。預設:process.stdout
。terminal
<boolean> 如果為true
,則指定應將output
視為 TTY 終端機。預設:在實例化時檢查output
串流上的isTTY
屬性的值。eval
<Function> 在評估每一行輸入時要使用的函式。預設:JavaScripteval()
函式的非同步包裝器。eval
函式可以repl.Recoverable
出錯,以指示輸入不完整並提示輸入其他行。useColors
<boolean> 如果為true
,則指定預設writer
函式應包含 ANSI 色彩樣式至 REPL 輸出。如果提供了自訂writer
函式,則此設定無效。預設:如果 REPL 實例的terminal
值為true
,則檢查output
串流上的色彩支援。useGlobal
<布林值> 如果為true
,指定預設評估函數將使用 JavaScriptglobal
作為內容,而不是為 REPL 執行個體建立一個新的獨立內容。節點 CLI REPL 將此值設定為true
。預設值:false
。ignoreUndefined
<布林值> 如果為true
,指定預設撰寫器不會輸出命令的回傳值,如果評估為undefined
。預設值:false
。writer
<函數> 在寫入output
之前,呼叫此函數以格式化每個命令的輸出。預設值:util.inspect()
。completer
<函數> 用於自訂 Tab 自動完成的選用函數。請參閱readline.InterfaceCompleter
以取得範例。replMode
<符號> 指定預設評估器在嚴格模式或預設(隨意)模式下執行所有 JavaScript 命令的旗標。可接受的值為repl.REPL_MODE_SLOPPY
以隨意模式評估表達式。repl.REPL_MODE_STRICT
以嚴格模式評估表達式。這等同於在每個 repl 陳述式之前加上'use strict'
。
breakEvalOnSigint
<布林值> 在收到SIGINT
時停止評估目前的程式碼片段,例如按下 Ctrl+C。這無法與自訂eval
函數一起使用。預設值:false
。preview
<布林值> 定義 repl 是否列印自動完成和輸出預覽。預設值:使用預設 eval 函數時為true
,在使用自訂 eval 函數時為false
。如果terminal
為 false,則沒有預覽,且preview
的值沒有作用。
- 傳回: <repl.REPLServer>
repl.start()
方法建立並啟動 repl.REPLServer
執行個體。
如果 options
是字串,則指定輸入提示
const repl = require('node:repl');
// a Unix style prompt
repl.start('$ ');
Node.js REPL#
Node.js 本身使用 node:repl
模組提供自己的互動介面來執行 JavaScript。這可透過執行 Node.js 二進位檔,而不傳遞任何參數(或傳遞 -i
參數)來使用
$ node
> const a = [1, 2, 3];
undefined
> a
[ 1, 2, 3 ]
> a.forEach((v) => {
... console.log(v);
... });
1
2
3
環境變數選項#
下列環境變數可自訂 Node.js REPL 的各種行為
NODE_REPL_HISTORY
:當提供有效路徑時,持續性 REPL 歷程記錄會儲存到指定的檔案,而不是使用者的家目錄中的.node_repl_history
。將此值設定為''
(空字串)會停用持續性 REPL 歷程記錄。空白會從值中移除。在 Windows 平台上,環境變數的空白值無效,因此請將此變數設定為一個或多個空白,以停用持續性 REPL 歷程記錄。NODE_REPL_HISTORY_SIZE
:控制在有歷程記錄時要持續保留多少行歷程記錄。必須是正數。預設值:1000
。NODE_REPL_MODE
:可能是'sloppy'
或'strict'
。預設值:'sloppy'
,允許執行非嚴格模式程式碼。
持續性歷程記錄#
預設情況下,Node.js REPL 會透過將輸入儲存至使用者家目錄中的 .node_repl_history
檔案,在 node
REPL 會話之間保留記錄。這項功能可透過設定環境變數 NODE_REPL_HISTORY=''
來停用。
使用進階行編輯器搭配 Node.js REPL#
對於進階行編輯器,請使用環境變數 NODE_NO_READLINE=1
啟動 Node.js。這將在正規終端機設定中啟動主程式和偵錯器 REPL,並允許搭配 rlwrap
使用。
例如,可以將下列內容新增至 .bashrc
檔案
alias node="env NODE_NO_READLINE=1 rlwrap node"
針對單一執行個體啟動多個 REPL 個體#
可以針對單一執行個體建立並執行多個 REPL 個體,這些個體共用單一 global
物件,但擁有個別的 I/O 介面。
例如,下列範例在 stdin
、Unix socket 和 TCP socket 上提供個別 REPL
const net = require('node:net');
const repl = require('node:repl');
let connections = 0;
repl.start({
prompt: 'Node.js via stdin> ',
input: process.stdin,
output: process.stdout,
});
net.createServer((socket) => {
connections += 1;
repl.start({
prompt: 'Node.js via Unix socket> ',
input: socket,
output: socket,
}).on('exit', () => {
socket.end();
});
}).listen('/tmp/node-repl-sock');
net.createServer((socket) => {
connections += 1;
repl.start({
prompt: 'Node.js via TCP socket> ',
input: socket,
output: socket,
}).on('exit', () => {
socket.end();
});
}).listen(5001);
從命令列執行此應用程式將在 stdin 上啟動 REPL。其他 REPL 應用程式可以透過 Unix socket 或 TCP socket 連線。例如,telnet
適用於連線至 TCP socket,而 socat
則可連線至 Unix 和 TCP socket。
透過從基於 Unix socket 的伺服器而非 stdin 啟動 REPL,可以連線至長期執行的 Node.js 程序,而無需重新啟動它。
如需透過 net.Server
和 net.Socket
個體執行「完整功能」(terminal
)REPL 的範例,請參閱:https://gist.github.com/TooTallNate/2209310。
如需透過 curl(1)
執行 REPL 個體的範例,請參閱:https://gist.github.com/TooTallNate/2053342。