从nodejs中的字符串调用函数

时间:2013-10-17 18:00:49

标签: string node.js function window global

nodejs中窗口[my_func_name]的等价物是什么?我正在从stdin读取一个字符串,如果它是一个函数名,我想执行它。我认为全局[my_func_name]可能有用但不幸的是它没有。

4 个答案:

答案 0 :(得分:12)

一切正常

global.foo = function foo () {
  console.log("foo was called");
}

process.stdin.on("data", function(input) {

  // don't forget to call .trim() to remove the \n
  var fn = input.toString().trim();

  // function exists
  if (fn in global && typeof global[fn] === "function") {
    global[fn]();
  }

  // function does not exist
  else {
    console.log("could not find " + fn + " function");
  }
});

process.stdin.resume();

输出

foo
foo was called
bar
could not find bar function

这是不是一个好主意...... 嗯,这是一个完全不同的讨论。


编辑 - ≈18个月后......是的,调用像这样的全局函数是一个可怕的想法。

在说,这是一种方式,你可以用更好的方式解决问题。下面我们将构建一个小REPL(read-eval-print循环)。为了更好地理解它,我将其分解为几个部分。

首先,我们要确保我们的REPL在尝试运行命令之前等待用户按Enter键。为此,我们将创建一个等待"\n"字符的transform stream,然后向管道发送line

  

以下代码使用ES6编写。如果您在查找兼容环境以运行代码时遇到问题,建议您查看babel

// line-unitizer.js
import {Transform} from 'stream';

class LineUnitizer extends Transform {
  constructor(delimiter="\n") {
    super();
    this.buffer = "";
    this.delimiter = delimiter;
  }
  _transform(chunk, enc, done) {
    this.buffer += chunk.toString();
    var lines = this.buffer.split(this.delimiter);
    this.buffer = lines.pop();
    lines.forEach(line => this.push(line));
    done();
  }
}

export default LineUnitizer;

如果您不熟悉流处理,请不要在LineUnitizer上过于沉重,而且它没有多大意义。这种流变换非常普遍。一般的想法是这样的:一旦我们将process.stdin传递到接收流中,process.stdin将在每次用户按下一个键时发出数据。但是,在用户完成键入命令之前,我们的Repl(在下面实现)无法对命令执行操作。 LineUnitizer是等待用户按Enter键(将"\n"插入流中)然后发信号通知_transform该命令已准备好发送到{{1}的部分处理!

让我们看一下repl现在

Repl
好吧,嘿,这很容易!它是做什么的?每次// repl.js import {Writable} from 'stream'; class Repl extends Writable { _parse(line) { var [cmd, ...args] = line.split(/\s+/); return {cmd, args}; } _write(line, enc, done) { var {cmd, args} = this._parse(line.toString()); this.emit(cmd, args); done(); } } export default Repl; 收到一行时,它会发出一个带有一些args的事件。这是一种可视方式,用于查看命令的解析方式

repl

好的,现在让我们将所有内容连接在一起以确保其正常工作

The user enters       emit event      args
-------------------------------------------------------------
add 1 2 3             "add"           ["1", "2", "3"]
hens chocobo cucco    "hens"          ["chocobo", "cucco"]
yay                   "yay"           []

运行它

// start.js
import LineUnitizer from './line-unitizer';
import Repl         from './repl';

process.stdin
  .pipe(new LineUnitizer())
  .pipe(
    (new Repl())
      .on("add", function(args) {
        var sum = args.map(Number).reduce((a,b) => a+b, 0);
        console.log("add result: %d", sum);
      })
      .on("shout", function(args) {
        var allcaps = args.map(s => s.toUpperCase()).join(" ");
        console.log(allcaps);
      })
      .on("exit", function(args) {
        console.log("kthxbai!");
        process.exit();
      }));

输出

  

前缀为$ node start.js 的行是用户输入。 {/ 1}}实际上不会在您的终端中显示。

>

如果你觉得这很棒,我们还没有完成。以这种方式编写程序的好处是,无论他们如何到达我们的程序,我们都可以对命令采取行动。

考虑这个>文件

> add 1 2 3
add result: 6
> shout I can see it in your face!
I CAN SEE IT IN YOUR FACE!
> exit
kthxbai!

现在像这样运行

commands.txt

输出

add 100 200
shout streams are the bee's knees
exit

好的,这太棒了。现在考虑命令可以来自任何地方。可能是一个数据库事件,网络上的东西,CRON工作等等。因为一切都很好地分开,我们可以轻松地调整这个程序,轻松接受各种输入。

答案 1 :(得分:1)

将您的函数写入单独的文件并导出它们并使用其名称引用来调用它们,如

//    functions.js
var funcOne = function(){
                   console.log('function ONE called')
              }
module.exports={
    //  name_exported : internal_name
    funcOne : funcOne
}

使用index.js中 functions.js 中定义的函数:

//    index.js
var methods = require('./functions.js')   // path to functions.js
methods['funcOne']()

输出:

> node index.js
> function ONE called

答案 2 :(得分:0)

var theTests = require('./tests'); 
//@TODO CaseID should be caseId
var CaseID = 5678;
// use dynamic functions
var functionName = 'theTests.TEST_' + CaseID;
var functionString = String('TEST_' + CaseID);

var check = eval( 'typeof ' + functionName ); // bad
if ( check == 'function' ) {
    // run the function
    // testResult = eval( functionName ); nope
    testResult = theTests[functionString](); //yep :)
    console.log(testResult);
}
else {
    console.log( 'No test functions for ' + CaseID );
}

在tests.js中的这个例子中 将寻找......

TEST_5678: function(){
     return some thing;
},

答案 3 :(得分:0)

我自己也遇到了同样的问题,我也是一个新手,所以带着一点盐-从其他posts here on SO提到global对象开始,我还发现{ {1}}似乎是Node.js中定义了module的本地对象。

因此,如果您在模块中:

exports

在某个时候,在声明导出之后(您可以在文件/脚本的顶部写导出,甚至在声明myFunction()之前),您可以调用:

exports.myFunction = myFunction;

这实际上将调用module.exports['myFunction']()

还是新手,所以要加些盐。