【问题标题】:Call JavaScript Function using object values as parameters使用对象值作为参数调用 JavaScript 函数
【发布时间】:2016-08-31 10:30:32
【问题描述】:

我有一个对象:

var obj = {
    foo: 'foo',
    bar: 'bar'
};

我有一个函数:

var f = function(bar, foo) {
    // Do something with bar and foo
};

有没有一种方法可以使用对象动态调用函数,使 obj['foo'] 作为 'foo' 参数传递,而 obj['bar'] 作为 'bar' 参数传递?请注意,我可能不知道键和值的实际名称或函数参数名称,提供的只是一个示例,所以f.call(this, obj['bar'], obj['foo']); 不会这样做。

【问题讨论】:

  • 你需要检查函数的参数名称,以正确的顺序创建一个参数数组,然后f.apply(null, args)…也许有人可以从这里提供一个实现…
  • 您想根据函数参数名称传递对象属性名称吗?这不是一个好主意。
  • 无法理解你想要什么。详细说明
  • @ajay OP 有一个对象,其键对应于函数的参数名称。 OP 想要调用函数,将对象中的适当值传递给函数的适当参数。

标签: javascript


【解决方案1】:

当然,在 ES6 中

var f = function({bar, foo}) {
    console.log('foo', foo, 'bar', bar)
};

var obj = {
    foo: '11',
    bar: '22'
};


f(obj)

【讨论】:

  • 不太一样……
  • 这可能不适用于Note that I may not know the actual names of the keys and values or the function argument names
【解决方案2】:

根据 deceze 的评论,我设法想出了一个解决方案。我不确定它有多快,但它可以完成工作。欢迎改进!感谢大家的帮助。

我从this answer使用了这个功能:

function getParameterNames(fn){
    var fstr = fn.toString();
    return fstr.match(/\(.*?\)/)[0].replace(/[()]/gi,'').replace(/\s/gi,'').split(',');
}

并做了以下:

var obj = {
    foo: 'foo',
    bar: 'bar'
};

var f = function(bar, foo) {
    // Do something with bar and foo
};

var sortedArgs = [];
getParameterNames(f).forEach(function(item) {
    sortedArgs.push(args[item]);
});

f.apply(this, sortedArgs);

【讨论】:

  • 如果您的源代码被转译和/或缩小会怎样?
  • 请注意:您所做的几乎就是 Angular 的注入工作原理,并且为了处理缩小问题,它有一个明确的注释语法,您需要在其中列出参数作为字符串 。所以,是的,这是一个真正的问题,这并不普遍适用……
  • 可以理解。实际上,我有多种方法可以使用特定参数调用该方法,这(使用对象)是其中一种方法。其他方式根据应传递的顺序使用参数调用方法。这样做的主要目的是用于内部开发,因此不会被缩小。
【解决方案3】:

您可以检查提供的参数是否为对象,然后使用解构

var obj = {
  foo: 'foo',
  bar: 'bar'
};

var f = function(foo, bar) {
  if(typeof arguments[0] == 'object') var {foo, bar} = arguments[0];
  console.log('Foo: ' + foo);
  console.log('Bar: ' + bar)
};

f(obj);
f('lorem', 'ipsum');

【讨论】:

  • 也不完全一样……
【解决方案4】:

您可以将对象bind 传递给函数。

bind() 方法创建一个新函数,在调用该函数时,将其 this 关键字设置为提供的值,在新函数被调用时,在任何提供的参数之前都有一个给定的参数序列调用。

var obj = {
        foo: 'foo',
        bar: 'bar'
    },
    f = function(k) {
        console.log(this[k]);
    }.bind(obj);

f('foo');

【讨论】:

    【解决方案5】:

    您可以编写一个函数来包装您的函数并使用新函数来获得您想要的。

    function wrapper(fn) {
      var fnString = fn.toString();
      var fnRegex = /\((.*)\)/;
    
      var params = fnString
        .match(fnRegex)[1]
        .replace(/\s/, '')
        .split(',')
        .filter(function(arg) {
          return arg;
        });
    
      return function (o) {
        var args = params
          .map(function(arg) {
            return o[arg];
          });
        return fn.apply(null, args);
      }
    }
    
    // Example: your function.
    function yourFunc(foo, bar) {
      console.log('my foo: ' + foo);
      console.log('my bar: ' + bar);
    }
    
    // wrap your function and use new function instead.
    var enhancedFunc = wrapper(yourFunc);
    
    enhancedFunc({foo: 1, bar: 2});

    【讨论】:

    • 您能否描述包装器的工作原理以及它如何根据键名以正确的顺序将参数传递给函数?
    • 首先,它解析fn.toString() 以获取正确顺序的参数数组。在示例中,fn.toString() => 'function yourFunc(foo, bar) {...}' => 'foo,bar' => ['foo', 'bar']。之后,它返回一个新函数,新函数使用上述数组获取值数组并使用该数组调用fn,['foo', 'bar'](与o 映射)=> [1, 2] => fn.apply(null, [1, 2])。
    猜你喜欢
    • 2012-07-14
    • 2017-06-23
    • 1970-01-01
    • 2011-06-23
    • 2016-05-24
    • 1970-01-01
    • 2016-04-09
    • 1970-01-01
    相关资源
    最近更新 更多