Node.js v12.4.0 文档


repl(交互式解释器)#

中英对照提交修改

稳定性: 2 - 稳定

repl 模块提供了一种“读取-求值-输出”循环(REPL)的实现,它可作为一个独立的程序或嵌入到其他应用中。 可以通过以下方式使用它:

const repl = require('repl');

设计与特性#

中英对照提交修改

repl 模块导出了 repl.REPLServer 类。 当 repl.REPLServer 实例运行时,它接收用户输入的每一行,根据用户定义的解释函数解释这些输入,然后输出结果。 输入可以是 stdin,输出可以是 stdout,或者也可以连接到其他任何 Node.js

repl.REPLServer 实例支持输入的自动补全、精简 Emacs 风格的行编辑、多行输入、ANSI 风格的输出、当前 REPL 会话状态的保存与恢复、错误校正、以及可定制的解释函数。

命令与特殊键#

查看v10.x中文文档

The following special commands are supported by all REPL instances:

  • .break - When in the process of inputting a multi-line expression, entering the .break command (or pressing the <ctrl>-C key combination) will abort further input or processing of that expression.
  • .clear - Resets the REPL context to an empty object and clears any multi-line expression currently being input.
  • .exit - Close the I/O stream, causing the REPL to exit.
  • .help - Show this list of special commands.
  • .save - Save the current REPL session to a file: > .save ./file/to/save.js
  • .load - Load a file into the current REPL session. > .load ./file/to/load.js
  • .editor - Enter editor mode (<ctrl>-D to finish, <ctrl>-C to cancel).
> .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!'
>

The following key combinations in the REPL have these special effects:

  • <ctrl>-C - When pressed once, has the same effect as the .break command. When pressed twice on a blank line, has the same effect as the .exit command.
  • <ctrl>-D - Has the same effect as the .exit command.
  • <tab> - When pressed on a blank line, displays global and local (scope) variables. When pressed while entering other input, displays relevant autocompletion options.

默认的解释器#

中英对照提交修改

默认情况下,所有 repl.REPLServer 实例使用了一个解释函数,它可以解释 JavaScript 表达式、提供对 Node.js 内置模块的访问。 当 repl.REPLServer 实例被创建时可以传入一个替换的解释函数,覆盖其默认的功能。

JavaScript 表达式#

查看v10.x中文文档

The default evaluator supports direct evaluation of JavaScript expressions:

> 1 + 1
2
> const m = 2
undefined
> m + 1
3

Unless otherwise scoped within blocks or functions, variables declared either implicitly or using the const, let, or var keywords are declared at the global scope.

全局作用域与局部作用域#

查看v10.x中文文档

The default evaluator provides access to any variables that exist in the global scope. It is possible to expose a variable to the REPL explicitly by assigning it to the context object associated with each REPLServer:

const repl = require('repl');
const msg = 'message';

repl.start('> ').context.m = msg;

Properties in the context object appear as local within the REPL:

$ node repl_test.js
> m
'message'

Context properties are not read-only by default. To specify read-only globals, context properties must be defined using Object.defineProperty():

const repl = require('repl');
const msg = 'message';

const r = repl.start('> ');
Object.defineProperty(r.context, 'm', {
  configurable: false,
  enumerable: true,
  value: msg
});

访问 Node.js 核心模块#

查看v10.x中文文档

The default evaluator will automatically load Node.js core modules into the REPL environment when used. For instance, unless otherwise declared as a global or scoped variable, the input fs will be evaluated on-demand as global.fs = require('fs').

> fs.createReadStream('./some/file');

全局的未捕获异常#

查看v10.x中文文档

The REPL uses the domain module to catch all uncaught exceptions for that REPL session.

This use of the domain module in the REPL has these side effects:

As standalone program:

process.on('uncaughtException', () => console.log('Uncaught'));

throw new Error('foobar');
// Uncaught

When used in another application:

process.on('uncaughtException', () => console.log('Uncaught'));
// TypeError [ERR_INVALID_REPL_INPUT]: Listeners for `uncaughtException`
// cannot be used in the REPL

throw new Error('foobar');
// Thrown:
// Error: foobar

_(下划线)变量的赋值#

查看v10.x中文文档

The default evaluator will, by default, assign the result of the most recently evaluated expression to the special variable _ (underscore). Explicitly setting _ to a value will disable this behavior.

> [ 'a', 'b', 'c' ]
[ 'a', 'b', 'c' ]
> _.length
3
> _ += 1
Expression assignment to _ now disabled.
4
> 1 + 1
2
> _
4

Similarly, _error will refer to the last seen error, if there was any. Explicitly setting _error to a value will disable this behavior.

> throw new Error('foo');
Error: foo
> _error.message
'foo'

await 关键词#

查看v10.x中文文档

With the --experimental-repl-await command line option specified, experimental support for the await keyword is enabled.

> await Promise.resolve(123)
123
> await Promise.reject(new Error('REPL await'))
Error: REPL await
    at repl:1:45
> const timeout = util.promisify(setTimeout);
undefined
> const old = Date.now(); await timeout(1000); console.log(Date.now() - old);
1002
undefined

自定义的解释函数#

中英对照提交修改

当创建一个新的 repl.REPLServer 时,可以提供一个自定义的解释函数。 这可以用于实现完全定制化的 REPL 应用。

例子,一个执行文本翻译的 REPL:

const repl = require('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 输出#

查看v10.x中文文档

By default, repl.REPLServer instances format output using the util.inspect() method before writing the output to the provided Writable stream (process.stdout by default). The showProxy inspection option is set to true by default and the colors option is set to true depending on the REPL's useColors option.

The useColors boolean option can be specified at construction to instruct the default writer to use ANSI style codes to colorize the output from the util.inspect() method.

If the REPL is run as standalone program, it is also possible to change the REPL's inspection defaults from inside the REPL by using the inspect.replDefaults property which mirrors the defaultOptions from util.inspect().

> util.inspect.replDefaults.compact = false;
false
> [1]
[
  1
]
>

To fully customize the output of a repl.REPLServer instance pass in a new function for the writer option on construction. The following example, for instance, simply converts any input text to upper case:

const repl = require('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 类#

中英对照提交修改

repl.REPLServer 类继承自 readline.Interface 类。 repl.REPLServer 的实例由 repl.start() 方法创建,不能直接使用 JavaScript 的 new 关键字创建。

'exit' 事件#

中英对照提交修改

当接收到 .exit 命令、或按下两次 <ctrl>-C 发出 SIGINT 信号、或按下 <ctrl>-D 发出 'end' 信号而使 REPL 被退出时,触发 'exit' 事件。 监听器的回调函数被调用时不带任何参数。

replServer.on('exit', () => {
  console.log('从 REPL 接收到 "exit" 事件!');
  process.exit();
});

'reset' 事件#

查看v10.x中文文档

The 'reset' event is emitted when the REPL's context is reset. This occurs whenever the .clear command is received as input unless the REPL is using the default evaluator and the repl.REPLServer instance was created with the useGlobal option set to true. The listener callback will be called with a reference to the context object as the only argument.

This can be used primarily to re-initialize REPL context to some pre-defined state:

const repl = require('repl');

function initializeContext(context) {
  context.m = 'test';
}

const r = repl.start({ prompt: '> ' });
initializeContext(r.context);

r.on('reset', initializeContext);

When this code is executed, the global 'm' variable can be modified but then reset to its initial value using the .clear command:

$ ./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 可以是一个函数或一个具有以下属性的对象:

  • help <string> 当键入 .help 时显示的帮助说明(可选)。
  • action <Function> 要执行的函数,可接受一个字符串参数。

例子,添加两个新命令到 REPL 实例:

const repl = require('repl');

const replServer = repl.start({ prompt: '> ' });
replServer.defineCommand('sayhello', {
  help: '打招呼',
  action(name) {
    this.clearBufferedCommand();
    console.log(`你好, ${name}!`);
    this.displayPrompt();
  }
});
replServer.defineCommand('saybye', function saybye() {
  console.log('再见!');
  this.close();
});

在 REPL 实例中使用新的命令:

> .sayhello Node.js中文网
你好,Node.js中文网!
> .saybye
再见!

replServer.displayPrompt([preserveCursor])#

中英对照提交修改

replServer.displayPrompt() 方法会让 REPL 实例做好用户输入的准备,打印配置的 promptoutput 中新的一行,然后返回 input 等待新的输入。

当正在键入多行输入时,会打印省略号而不是提示符。

preserveCursortrue 时,游标位置不会被复位到 0

replServer.displayPrompt 方法主要被使用 replServer.defineCommand() 方法注册的命令的 action 函数调用。

replServer.clearBufferedCommand()#

中英对照提交修改

replServer.clearBufferedCommand() 方法清除已缓冲但尚未执行的任何命令。 此方法主要用于在使用 replServer.defineCommand() 方法注册的命令的 action 函数内调用。

replServer.parseREPLKeyword(keyword[, rest])#

暂无中英对照

  • keyword <string> the potential keyword to parse and execute
  • rest <any> any parameters to the keyword command
  • Returns: <boolean>

稳定性: 0 - 废弃.

An internal method used to parse and execute REPLServer keywords. Returns true if keyword is a valid keyword, otherwise false.

replServer.setupHistory(historyPath, callback)#

暂无中英对照

Initializes a history log file for the REPL instance. When executing the Node.js binary and using the command line REPL, a history file is initialized by default. However, this is not the case when creating a REPL programmatically. Use this method to initialize a history log file when working with REPL instances programmatically.

repl.start([options])#

查看v10.x中文文档

  • options <Object> | <string>

    • prompt <string> The input prompt to display. Default: '> ' (with a trailing space).
    • input <stream.Readable> The Readable stream from which REPL input will be read. Default: process.stdin.
    • output <stream.Writable> The Writable stream to which REPL output will be written. Default: process.stdout.
    • terminal <boolean> If true, specifies that the output should be treated as a TTY terminal. Default: checking the value of the isTTY property on the output stream upon instantiation.
    • eval <Function> The function to be used when evaluating each given line of input. Default: an async wrapper for the JavaScript eval() function. An eval function can error with repl.Recoverable to indicate the input was incomplete and prompt for additional lines.
    • useColors <boolean> If true, specifies that the default writer function should include ANSI color styling to REPL output. If a custom writer function is provided then this has no effect. Default: checking color support on the output stream if the REPL instance's terminal value is true.
    • useGlobal <boolean> If true, specifies that the default evaluation function will use the JavaScript global as the context as opposed to creating a new separate context for the REPL instance. The node CLI REPL sets this value to true. Default: false.
    • ignoreUndefined <boolean> If true, specifies that the default writer will not output the return value of a command if it evaluates to undefined. Default: false.
    • writer <Function> The function to invoke to format the output of each command before writing to output. Default: util.inspect().
    • completer <Function> An optional function used for custom Tab auto completion. See readline.InterfaceCompleter for an example.
    • replMode <symbol> A flag that specifies whether the default evaluator executes all JavaScript commands in strict mode or default (sloppy) mode. Acceptable values are:

      • repl.REPL_MODE_SLOPPY - evaluates expressions in sloppy mode.
      • repl.REPL_MODE_STRICT - evaluates expressions in strict mode. This is equivalent to prefacing every repl statement with 'use strict'.
    • breakEvalOnSigint - Stop evaluating the current piece of code when SIGINT is received, i.e. Ctrl+C is pressed. This cannot be used together with a custom eval function. Default: false.
  • Returns: <repl.REPLServer>

The repl.start() method creates and starts a repl.REPLServer instance.

If options is a string, then it specifies the input prompt:

const repl = require('repl');

// a Unix style prompt
repl.start('$ ');

Node.js 的 REPL#

查看v10.x中文文档

Node.js itself uses the repl module to provide its own interactive interface for executing JavaScript. This can be used by executing the Node.js binary without passing any arguments (or by passing the -i argument):

$ 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 历史记录。 值两头的空格键会被去掉。
  • NODE_REPL_HISTORY_SIZE - 默认为 1000。控制历史记录的最大行数。必须是正数。
  • NODE_REPL_MODE - 可以是 'sloppy''strict'。  默认是 'sloppy', 在 'sloppy' 模式下,允许代码在非严格模式下运行。

历史记录#

中英对照提交修改

默认情况下,Node.js REPL 模块会把 node REPL 会话之间的历史记录保存到用户目录中的 .node_repl_history 文件。 修改环境变量 NODE_REPL_HISTORY='' 可以禁用该功能。

在高级的行编辑器中使用 Node.js REPL#

中英对照提交修改

对于高级的行编辑器,可以使用环境变量 NODE_NO_READLINE=1 来启动 Node.js。 这会以标准的终端配置来启动主 REPL 和调试 REPL,可以使用 rlwrap

例如,可以在 .bashrc 文件中添加:

alias node="env NODE_NO_READLINE=1 rlwrap node"

在一个 Node.js 实例中启动多个 REPL 实例#

查看v10.x中文文档

It is possible to create and run multiple REPL instances against a single running instance of Node.js that share a single global object but have separate I/O interfaces.

The following example, for instance, provides separate REPLs on stdin, a Unix socket, and a TCP socket:

const net = require('net');
const repl = require('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);

Running this application from the command line will start a REPL on stdin. Other REPL clients may connect through the Unix socket or TCP socket. telnet, for instance, is useful for connecting to TCP sockets, while socat can be used to connect to both Unix and TCP sockets.

By starting a REPL from a Unix socket-based server instead of stdin, it is possible to connect to a long-running Node.js process without restarting it.

For an example of running a "full-featured" (terminal) REPL over a net.Server and net.Socket instance, see: https://gist.github.com/TooTallNate/2209310.

For an example of running a REPL instance over curl(1), see: https://gist.github.com/TooTallNate/2053342.