在JavaScript中使用对象中的正确参数调用函数

时间:2014-08-08 23:09:38

标签: javascript node.js function reflection

让我们说我的对象看起来像这样:

{
     'apple': 'nice',
     'banana': 'decent',
     'cherry': 'yuck',
}

我有这两种方法:

function eatItems(cherry, apple) { }
function throwItem(banana) { }

我的两个问题:

  1. 我可以调用eatItem并以正确的顺序发送参数吗?也许是这样的:

    eatItems.call(this,{' cherry&#39 ;: cherry,' apple&#39 ;: apple});

  2. 如果我不知道eatItems接收到什么参数,我可以动态查找函数参数的名称,这样我就可以知道我需要将它们放入的顺序吗?

2 个答案:

答案 0 :(得分:2)

确实有一种方法,它涉及在函数上调用toString

var source = eatItems.toString();
// => "function eatItems(cherry, apple) { }"

下一步是解析您获取参数名称的字符串:

var args = source.substring(source.indexOf("(") + 1, source.indexOf(")")),
    argNames = /\S/.test(args) ? args.split(/\s*,\s*/) : [];

一些警告:

  1. 这个解决方案一直很简单。它不会处理函数定义中的注释。
  2. 并非每个浏览器都能正确地将函数转换为字符串(PS3浏览器出现在我的脑海中),但无论如何它们都是一个非常小的少数。
  3. 我还没有对其进行测试,但在速度较慢的计算机和/或功能较大的旧版浏览器上可能存在一些性能问题。
  4. 总的来说,这个解决方案更像是一个练习。我不建议在Javascript中使用这种模式。不要忘记某些函数处理可变数量的参数,并且您不会在其定义中找到它们。重新思考你的代码,找到更好的方法。

答案 1 :(得分:1)

如果我理解正确,您需要从函数中提取参数名称,并根据这些名称从对象中注入数据。这可以通过将函数转换为字符串,提取参数,并使用这些参数应用函数来实现:

function inject(data, f) {
  var args = f.toString()
    .match(/function\s*?\((.+?)\)/)
    .pop()
    .split(',')
    .map(function(a){return data[a.trim()]})
  return function() {
    return f.apply(this, args)
  }
}

var data = {
  apple: 'nice',
  banana: 'decent',
  cherry: 'yuck',
}

var eat = inject(data, function(cherry, apple) {
  console.log(cherry, apple)
})

eat() //=> yuck, nice

这种方法的一个明显问题是它高度依赖于变量名,因此当你缩小代码时,变量会被破坏,函数将停止工作。这是AngularJS中的一个已知问题,它使用类似的依赖注入。

这通常是XY问题,或者至少是反模式。