关于javascript:如何将我的脚本加载到node.js REPL中?

How do I load my script into the node.js REPL?

我有一个脚本foo.js,其中包含一些我想在repl中使用的函数。

有没有一种方法可以让节点执行我的脚本,然后像使用python -i foo.pyghci foo.hs那样,使用所有声明的全局变量跳转到repl?


仍然没有内置的功能来提供您所描述的确切功能。但是,在repl中使用requireit来使用.load命令的一种替代方法,如:

1
.load foo.js

它一行一行地加载文件,就像在repl中键入文件一样。与require不同,这会用您加载的命令污染repl历史记录。但是,它具有可重复的优点,因为它不像require那样缓存。

哪一个更适合您,取决于您的用例。

编辑:它的适用性有限,因为它不在严格模式下工作,但三年后我了解到如果您的脚本没有'use strict',您可以使用eval加载脚本,而不会污染repl历史:

1
2
var fs = require('fs');
eval(fs.readFileSync('foo.js').toString())


我总是用这个命令

1
node -i -e"$(< yourScript.js)"

在没有任何包的情况下,与在Python中一样工作。


我制作了vorpal.js,它通过将node add转换为交互式cli来处理这个问题。它支持一个repl扩展,将您放入运行应用程序上下文中的repl中。

1
2
3
4
5
6
7
8
var vorpal = require('vorpal')();
var repl = require('vorpal-repl');

vorpal
  .delimiter('myapp>')
  .use(repl)
  .show()
  .parse(process.argv);

然后你可以运行这个应用程序,它将进入一个repl。

1
2
$ node myapp.js repl
myapp> repl:

另一种方法是将这些函数定义为全局函数。

1
global.helloWorld = function() { console.log("Hello World"); }

然后将repl中的文件预加载为:

1
node -r ./file.js

然后可以在repl中直接访问函数helloWorld


我创建了replpad,因为我厌倦了重复加载脚本。

只需通过:npm install -g replpad安装即可。

然后运行:replpad

如果您希望它监视当前目录和所有子目录中的所有文件,并在文件更改时将其传输到repl中:replpad .

查看网站上的视频,更好地了解它的工作原理,并了解它具有的其他一些不错的功能:

  • 通过添加到每个核心功能中的dox()功能访问repl中的核心模块文档,即fs.readdir.dox()
  • 通过添加到通过NPM安装的每个模块中的dox()功能访问repl中的用户模块自述,即marked.dox()
  • 访问函数突出显示的源代码、定义函数的位置信息(文件、行号)和函数可能的话,通过添加到每个函数的src属性的注释和/或jsdoc,即express.logger.src
  • 脚本对讲机支持(见.talk命令)
  • 添加命令和键盘快捷键
  • VIM键绑定
  • 关键地图支持
  • 通过匹配令牌插件进行parens匹配
  • 通过键盘快捷键或.append命令将repl back中输入的代码附加到文件中


为什么不将文件加载到交互式节点repl中?

1
2
3
4
5
node -h
-e, --eval script          evaluate script
-i, --interactive          always enter the REPL even if stdin

node -e 'var client = require("./build/main/index.js"); console.log("Use `client` in repl")' -i

然后可以添加到package.json脚本

1
"repl":"node -e 'var client = require("./build/main/index.js"); console.log("Use `client` in repl")' -i",

使用节点V8.1.2进行测试


replpad很酷,但是为了快速简便地将文件加载到节点、导入其变量并启动repl,可以在.js文件的末尾添加以下代码

1
2
3
4
5
6
7
8
9
10
if (require.main === module){
    (function() {
        var _context = require('repl').start({prompt: '$> '}).context;
        var scope = require('lexical-scope')(require('fs').readFileSync(__filename));
        for (var name in scope.locals[''] )
            _context[scope.locals[''][name]] = eval(scope.locals[''][name]);
        for (name in scope.globals.exported)
            _context[scope.globals.exported[name]] = eval(scope.globals.exported[name]);
    })();
}

现在,如果您的文件是src.js,运行node src.js将启动节点,加载文件,启动repl,并复制顶级声明为var的所有对象以及任何导出的全局对象。if (require.main === module)确保如果src.js通过require语句包含,则不会执行此代码。事实上,您可以在if语句中添加任何在运行src.js独立代码以进行调试时想要执行的代码。


目前您不能直接这样做,但您可以在repl中mylib = require('./foo.js')。请记住,方法是导出的,而不是声明为全局的。


以下是bash函数版本乔治的回答:

1
2
3
4
noderepl() {
    FILE_CONTENTS="$(< $1 )"
    node -i -e"$FILE_CONTENTS"
}

如果你把它放在你的~/.bash_profile里,你可以像化名一样使用它,即:

1
noderepl foo.js


另一个我在这里看不到的建议是:尝试这一小段代码

1
2
3
4
5
6
#!/usr/bin/env node
'use strict';

const repl = require('repl');
const cli = repl.start({ replMode: repl.REPL_MODE_STRICT });
cli.context.foo = require('./foo'); // injects it into the repl

然后您可以简单地运行这个脚本,它将包括foo作为一个变量


旧答案

1
type test.js|node -i

将打开节点repl并在test.js中的所有行中键入repl,但由于某种原因,文件结束后节点将退出。

另一个问题是,该功能将不会被提升。

更好的答案

1
node -e require('repl').start({useGlobal:true}); -r ./test2.js

那么,在test2.js中声明的没有var的所有全局变量将在repl中可用。

不确定为什么全局范围中的var a不可用