如何从方法名称数组构造方法链

时间:2019-02-06 07:08:41

标签: javascript arrays function substring

让我向您展示我要完成的事情的一个例子:

说我想调用函数子函数的子函数的子函数(依此类推,比如说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"]]]

2 个答案:

答案 0 :(得分:5)

使用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的当前范围内。

答案 1 :(得分:1)

尝试

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 );