【问题标题】:How to construct a method chain from an array of method names如何从方法名称数组构造方法链
【发布时间】:2019-02-06 07:08:41
【问题描述】:

让我给你看一个我想要完成的例子:

假设我想调用一个函数的子函数的子函数的子函数(等等,比如说 50 多个子函数),比如:

foo(arg).bar(other).foobar(int, str).execute(str)

假设有 50 多个子函数,因此键入每个子调用是非常不切实际的。

SO:我如何编写一个函数来调用子函数的子函数等...(基于数组长度)?,基于这样的数组(对于示例):

[["foo",["asdf"]],["bar",["other"]],["foobar",[123,"hi"]],["execute",["today"]]]

需要明确的是,我并不是简单地尝试使用相应的参数单独调用数组中的每个函数,我可以通过以下方式轻松做到这一点:

arr.forEach(x=>functionDictionary(x[0])(...x[1])

我只想得到这个:

foo(arg).bar(other).foobar(int, str).execute(str)

从此:

[["foo",["asdf"]],["bar",["other"]],["foobar",[123,"hi"]],["execute",["today"]]]

【问题讨论】:

  • “在另一个方法的返回值上调用一个方法” 会更好的措辞。 “从方法名称数组构造方法链”会更好。
  • @Eric 好主意 :)

标签: javascript arrays function substring


【解决方案1】:

使用reduce遍历数组并调用每个函数,并将返回值作为累加器传递给下一次迭代:

// using just a single object to make the indentation much more readable:
const obj = {
  foo(arg) {
    console.log('foo called with ' + arg);
    return this;
  },
  bar(arg2) {
    console.log('bar called with ' + arg2);
    return this;
  },
  foobar(argA, argB) {
    console.log('foobar called with ' + argA + ' ' + argB);
    return this;
  },
  execute(arg5) {
    console.log('execute called with ' + arg5);
    return this;
  }
};

const arr = [
  ["foo", ["asdf"]],
  ["bar", ["other"]],
  ["foobar", [123, "hi"]],
  ["execute", ["today"]]
];
arr.reduce((a, [key, args]) => a[key](...args), obj);

注意这里我传入obj作为初始值,这样第一个["foo"]就可以访问obj.foo,而不是使用eval来引用当前作用域中名为foo的变量.

【讨论】:

  • 哇,这真的很酷,我什至不知道 reduce 方法!而且我不知道你可以在对象文字中声明这样的函数......如果每个函数都没有返回值,是否可以做同样的事情?
  • 如果函数没有返回任何内容,那么您想要的 foo(arg).bar(other).foobar(int, str).execute(str) 输出调用格式没有意义。如果所有函数都在一个对象或其他东西中,就像我的回答一样,那么您可以在每次迭代时简单地访问对象的适当属性。
  • 我承认你是对的,我错了,但是另一个答案不需要使用reduce(没有反对reduce,它只是一个额外的步骤)
  • 我选择了reduce,因为它是完全独立的——不需要额外的外部变量。另一个答案的外部变量更像是一个额外的步骤
  • 我猜但是如果其中一个对象碰巧没有返回变量/不可调用,有没有办法检查?
【解决方案2】:

试试

arr.forEach( x => r=r[x[0]](...x[1]) );

其中 arr 包含带有函数名称参数的数组, r 包含带有函数的对象(最后是结果)。

const o = {
  fun1(arg) { console.log('fun1 ' + arg); return this;},
  fun2(arg1,arg2) { console.log('fun2 ' + arg1 +'-'+ arg2); return this; },
  fun3(arg) { console.log('fun3 ' + arg); return this;},  
};

const arr = [
  ["fun1", ["abc"]],  
  ["fun2", [123, "def"]],
  ["fun3", ["ghi"]]
];


let r=o; // result
arr.forEach( x => r=r[x[0]](...x[1]) );

如果你想在函数不返回下一个对象时中断调用链,那么使用这个

arr.forEach( x => r= r ? r[x[0]](...x[1]) : 0 );

const o = {
  fun1(arg) { console.log('fun1 ' + arg); return this;},
  fun2(arg1,arg2) { console.log('fun2 ' + arg1 +'-'+ arg2); },
  fun3(arg) { console.log('fun3 ' + arg); return this;},  
};

const arr = [
  ["fun1", ["abc"]],  
  ["fun2", [123, "def"]],
  ["fun3", ["ghi"]]
];


let r=o; // result
arr.forEach( x => r= r ? r[x[0]](...x[1]) : 0 );

【讨论】:

    猜你喜欢
    • 2013-11-01
    • 1970-01-01
    • 2015-10-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-22
    • 1970-01-01
    • 2015-05-22
    • 2019-08-23
    相关资源
    最近更新 更多