javascript - 如何动态创建一个方法,并将可变数量的参数存储在变量中?

标签 javascript function binding delegation arity

为了设置 Socket.IO 客户端,我有很多如下所示的方法:

myobject.prototype.A = function (callback) {
    this.foo('a', null, callback);
}

myobject.prototype.B = function (bar, callback) {
    this.foo('b', { bar }, callback);
}

myobject.prototype.C = function (baz, qux, callback) {
    this.foo('c', { baz, qux }, callback);
}

this.foo 的内容并不重要,但它需要 3 个参数:一个字符串、一个根据调用方法参数构建的对象和一个回调方法。

我希望将这些方法设置在一个地方。我想要看起来像这样的东西:

// I'm not sure what form the args should take
const methods = {
  A: { socketName: 'a', args: [ ] },
  B: { socketName: 'b', args: [ 'bar' ] },
  C: { socketName: 'c', args: [ 'baz', 'qux' ] }
};

for (let m in methods) {
    const mData = methods[m];
    this.prototype[m] = function (what_do_I_put_here_?, callback) {
        // how do I form "otherArgs" ?
        this.foo(mData.socketName, otherArgs, callback);
    }
}

我想我必须考虑解构赋值,但我不确定在这种情况下如何使用它们。

最佳答案

您可以利用闭包和数组函数来做到这一点:

"use strict"
class Test {

  createDynFoo(name, propertyNames = []) {
    // return an arrow function (ensures that this is still the obj)
    return (x, ...args) => {
      let obj = null; // set obj to null as default
      if (args.length > 0) {
        // if we have additional aguments to x we create an obj
        obj = {};
        // map the additional arguments to the property names
        propertyNames.forEach((value, idx) => {
          obj[value] = args[idx]
        })
      }
      // call the actual foo function
      return this.foo(name, x, obj)
    }
  }

  foo(name, x, obj) {
    console.log(`${name} ${x}`)
    console.dir(obj);
  }
}

let test = new Test();


let tiggerForA = test.createDynFoo('a');
let tiggerForB = test.createDynFoo('b', ['y']);
let tiggerForC = test.createDynFoo('c', ['y', 'z']);

tiggerForA(1);
tiggerForB(1, 2);
tiggerForC(1, 2, 3);

如果您确实需要它作为成员函数,您可以这样做:

"use strict"
class Test {

  constructor() {
    this.A = this.createDynFoo('a');
    this.B = this.createDynFoo('b', ['y']);
    this.C = this.createDynFoo('c', ['y', 'z']);
  }


  createDynFoo(name, propertyNames = []) {
    // return an arrow function (ensures that this is still the obj)
    return (x, ...args) => {
      let obj = null; // set obj to null as default
      if (args.length > 0) {
        // if we have additional aguments to x we create an obj
        obj = {};
        // map the additional arguments to the property names
        propertyNames.forEach((value, idx) => {
          obj[value] = args[idx]
        })
      }
      // call the actual foo function
      return this.foo(name, x, obj)
    }
  }

  foo(name, x, obj) {
    console.log(`${name} ${x}`)
    console.dir(obj);
  }
}

let test = new Test();


test.A(1);
test.B(1, 2);
test.C(1, 2, 3);

如果它只是关于成员函数,你可以像这样去掉箭头函数:

"use strict"



function createDynFunction(classObj, targetFunctionName, newFunctionName, name, propertyNames = []) {
  // create a new function and assigned it to the prototype of the class
  classObj.prototype[newFunctionName] = function(x, ...args) {
    let obj = null; // set obj to null as default
    if (args.length > 0) {
      // if we have additional aguments to x we create an obj
      obj = {};
      // map the additional arguments to the property names
      propertyNames.forEach((value, idx) => {
        obj[value] = args[idx]
      })
    }
    // call the actual foo function
    return this[targetFunctionName](name, x, obj)
  }
}

class Test {
  foo(name, x, obj) {
    console.log(`${name} ${x}`)
    console.dir(obj);
  }
}

createDynFunction(Test, 'foo', 'A', 'a');
createDynFunction(Test, 'foo', 'B', 'b', ['y']);
createDynFunction(Test, 'foo', 'C', 'c', ['y', 'z']);

let test = new Test();

test.A(1);
test.B(1, 2);
test.C(1, 2, 3);

由于我不知道确切的用例,因此很难想出完全符合需求的解决方案。但根据显示的代码,您应该了解如何实现这一点。

关于javascript - 如何动态创建一个方法,并将可变数量的参数存储在变量中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77352609/

相关文章:

javascript enter 事件在谷歌上不起作用

从头文件中声明的另一个文件调用函数

javascript - JS - 从对象中删除键

java - PHP在Java中的range函数

java - JBoss 绑定(bind) IP 地址

javascript - Chart.js 绘制自定义网格线

javascript - 如何使用 JavaScript 比较软件版本号? (只有数字)

javascript - 计算 click() 函数被使用了多少次

wpf - MVVM 将 viewmodel 属性子项绑定(bind)到 viewmodel 属性

binding - Clojure:在 let 绑定(bind)中展开 var