### 穩定度: 2 - 穩定
一個 讀取-執行-打印-循環(REPL)可以用于單獨的程序,也能很容易的被集成在其他程序中。`REPL`提供了一種交互著運行`JavaScript`然后查看結果的方式。它可以被用來調試,測試或只是嘗試一些東西。
在命令行中不帶任何參數直接執行`iojs`,你會進入REPL界面。它有一個極簡的emacs行編輯器。
~~~
mjr:~$ iojs
Type '.help' for options.
> a = [ 1, 2, 3];
[ 1, 2, 3 ]
> a.forEach(function (v) {
... console.log(v);
... });
1
2
3
~~~
要使用高級的行編輯器的話,帶著環境變量`NODE_NO_READLINE=1`啟動`io.js`。它將會在允許你使用`rlwrap`的終端設置中,啟動一個主要的調試`REPL`(main and debugger REPL)。
例如,你可以把以下內容加入`bashrc`文件:
~~~
alias iojs="env NODE_NO_READLINE=1 rlwrap iojs"
~~~
內置的`REPL`(通過運行`iojs`或`iojs -i`啟動)可以被以下環境變量所控制:
- NODE_REPL_HISTORY_FILE - 如果指定,那必須是一個用戶可讀也可寫的文件路徑。當給定了一個可用的路徑,將啟用持久化的歷史記錄支持:`REPL`歷史記錄將會跨`iojs``REPL`會話持久化。
- NODE_REPL_HISTORY_SIZE - 默認為`1000`。與`NODE_REPL_HISTORY_FILE`結合,控制需要持久化的歷史記錄數量。必須為正數。
- NODE_REPL_MODE - 可以是`sloppy`,`strict`或`magic`中的一個。默認為`magic`,會自動在嚴格模式中執行`"strict mode only"`聲明。
#### repl.start(options)
返回并啟動一個`REPLServer`實例,繼承于`[Readline Interface][]`。接受一個包含以下值得`options`對象:
-
prompt - 所有`I/O`的提示符。默認為`>`。
-
input - 監聽的可讀流。默認為`process.stdin`。
-
output - 輸出數據的可寫流。默認為`process.stdout`。
-
terminal - 如果流需要被像TTY對待,并且有`ANSI/VT100`轉義代碼寫入,設置其為`true`。默認為在實例化時檢查到的`output`流的`isTTY`屬性。
-
eval - 被用來執行每一行的函數。默認為被異步包裝過的`eval()`。參閱下文的自定義`eval`的例子。
-
useColors - 一個表明了是否`writer`函數需要輸出顏色的布爾值。如果設置了不同的`writer`函數,那么它什么都不會做。默認為`REPL`的終端值。
-
useGlobal - 若設置為`true`,那么`REPL`將使用全局對象,而不是運行每一個腳本在不同上下文中。默認為`false`。
-
ignoreUndefined - 若設置為`true`,那么如果返回值是`undefined`,`REPL`將不會輸出它。默認為`false`。
-
writer - 當每一個命令被執行完畢時,都會調用這個函數,它返回了展示的格式(包括顏色)。默認為`util.inspect`。
-
**replMode** - 控制是否`REPL`運行所有的模式在嚴格模式,默認模式,或混合模式(`"magic"`模式)。接受以下值:
- repl.REPL_MODE_SLOPPY - 在混雜模式下運行命令。
- repl.REPL_MODE_STRICT - 在嚴格模式下運行命令。這與在每個命令前添加`'use strict'`語句相等。
- repl.REPL_MODE_MAGIC - 試圖在默認模式中運行命令,如果失敗了,會重新嘗試使用嚴格模式。
你可以使用你自己的`eval`函數,如果它包含以下簽名:
~~~
function eval(cmd, context, filename, callback) {
callback(null, result);
}
~~~
在用tab補全時 - `eval`將會帶著一個作為輸入字符串的`.scope`調用。它被期望返回一個`scope`名字數組,被用來自動補全。
多個`REPL`可以運行相同的`io.js`實例。共享同一個全局對象,但是各自的I/O獨立。
下面是在`stdin`,Unix `socket` 和 TCP `socket` 上啟動一個`REPL`的例子:
~~~
var net = require("net"),
repl = require("repl");
connections = 0;
repl.start({
prompt: "io.js via stdin> ",
input: process.stdin,
output: process.stdout
});
net.createServer(function (socket) {
connections += 1;
repl.start({
prompt: "io.js via Unix socket> ",
input: socket,
output: socket
}).on('exit', function() {
socket.end();
})
}).listen("/tmp/iojs-repl-sock");
net.createServer(function (socket) {
connections += 1;
repl.start({
prompt: "io.js via TCP socket> ",
input: socket,
output: socket
}).on('exit', function() {
socket.end();
});
}).listen(5001);
~~~
在命令行中運行這個程序會在`stdin`上啟動一個`REPL`。另外的`REPL`客戶端將會通過Unix `socket`或TCP `socket`連接。`telnet`在連接TCP `socket`時非常有用,`socat`在連接Unix `socket`和TCP `socket`時都非常有用。
通過從基于Unix `socket` 的服務器啟動`REPL`,你可以不用重啟,而連接到一個長久執行的(long-running)`io.js`進程。
一個通過`net.Server`和`net.Socket`實例運行“全特性”(終端)`REPL`的例子,參閱`https://gist.github.com/2209310`。
一個通過`curl(1)`運行`REPL`的例子,參閱`https://gist.github.com/2053342`。
#### Event: 'exit'
- function () {}
當用戶通過任意一種已定義的方式退出`REPL`時觸發。具體地說,在`REPL`中鍵入`.exit`,兩次按下`Ctrl+C`來發送`SIGINT`信號,按下`Ctrl+D`來發送結束信號。
例子:
~~~
r.on('exit', function () {
console.log('Got "exit" event from repl!');
process.exit();
});
~~~
#### Event: 'reset'
- function (context) {}
當`REPL`內容被重置時觸發。當你鍵入`.clear`時發生。如果你以`{ useGlobal: true }`啟動`REPL`,那么這個事件將永遠不會觸發。
例子:
~~~
// Extend the initial repl context.
r = repl.start({ options ... });
someExtension.extend(r.context);
// When a new context is created extend it as well.
r.on('reset', function (context) {
console.log('repl has a new context');
someExtension.extend(context);
});
~~~
### REPL 特性
在`REPL`內,按下`Control+D`將會退出。多行表達式可以被輸入。Tab補全同時支持全局和本地變量。
核心模塊將會被按需載入環境。例如,調用`fs`,將會從`global.fs`獲取,作為`require()``fs`模塊的替代。
特殊的變量`_`(下劃線)包含了上一個表達式的結果。
~~~
> [ "a", "b", "c" ]
[ 'a', 'b', 'c' ]
> _.length
3
> _ += 1
4
~~~
`REPL`可以訪問全局作用域里的任何變量。你可以通過將變量賦值給一個關聯了所有`REPLServer`的`context`對象來暴露一個對象給`REPL`。例子:
~~~
// repl_test.js
var repl = require("repl"),
msg = "message";
repl.start("> ").context.m = msg;
~~~
`context`對象里的對象會表現得像`REPL`的本地變量:
~~~
mjr:~$ iojs repl_test.js
> m
'message'
~~~
以下是一些特殊的`REPL`命令:
- .break - 當你輸入一個多行表達式時,有時你走神了,或有時你不關心如何完成它了。`.break`將會讓你重新來過。
- .clear - 重置`context`對象為一個空對象并且清除所有多行表達式。
- .exit - 關閉I/O流,意味著會導致`REPL`退出。
- .help - 展示特殊命令列表。
-
**.save** 將當前的`REPL`會話保存入一個文件。
- `.save ./file/to/save.js`
-
**.load** - 從一個文件中加載`REPL`會話。
- `.load ./file/to/load.js`
這些組合鍵在`REPL`中有以下影響:
- ctrl + C - 與`.break`關鍵字相似。終止當前命令。在一個空行上連按兩次會強制退出。
- ctrl + D - 與`.exit`關鍵字相似。
- tab - 展示所有的全局和本地變量。