【问题标题】:JavaScript function arguments: positional -> map transitionJavaScript 函数参数:位置 -> 地图转换
【发布时间】:2015-05-04 12:26:27
【问题描述】:

我正在寻找 vanilla JavaScript 解决方案。

假设我有一个带有以下标头的函数:

generateEmail(firstName, lastname, provider)

我需要像这样运行它:

generateEmail("John","Smith","gmail.com");

我希望能够使用参数映射而不是位置参数来调用它,即

generateEmail({
  "firstName":"John",
  "lastname": "Smith",
  "provider": "gmail.com"
});

我正在寻找一个已经编写好的解决方案来用 JavaScript 执行此操作,因为我有无限数量的函数,例如上面的 generateEmail 来处理。有这样的库吗?

我见过https://github.com/kilianc/node-introspect 处理函数自省(返回函数抽象参数信息)。但是缺少第二部分 - 将地图调用映射到位置调用。

请告诉我,这样的事情是否存在。


编辑:如果我没有说清楚:我不想修改原来的位置参数函数。我从可能会更新他的代码的外部提供商那里获得此类功能。我宁愿有一个包装器,它可以调用下面的原始函数,并在外面提供一个 map-argument API。

【问题讨论】:

  • 您可以检查firstName 是否是一个对象,然后使用适当的参数再次调用generateEmail
  • @GaurangTandon 这完全是我不需要需要的。我需要一个通用的包装函数来处理我写的东西。我可以自己写,但首先我想检查一下,如果这样的东西已经存在。
  • 我会说使用 stackoverflow.com/questions/914968/….apply 的组合这是可能的。
  • @EvanKnowles 我知道链接并且知道使用.apply;主要是我知道如何写这样的东西,但我不喜欢重新发明轮子:) 我更喜欢使用现有的解决方案。

标签: javascript function dictionary syntax arguments


【解决方案1】:

假设您可以从node-introspect 访问introspect(它接受一个函数并返回参数名称的有序列表),您可以简单地执行以下操作:

function objArgsify(fn) {
    var argNames = introspect(fn);
    return function(obj) {
        return fn.apply(this,
                        argNames.map(function(a) { return obj[a]; });
    }
}

调用方式:

var generateEmailWithObjArgs = objArgsify(generateEmail);
generateEmailWithObjArgs({
  "firstName":"John",
  "lastname": "Smith",
  "provider": "gmail.com"
});

这接受一个函数,读取它的参数名称,然后返回一个包装函数,该函数接受一个对象并使用位置参数名称以正确的顺序从对象参数中提取属性。

此函数使用调用时对象参数作为映射将数组["firstName", "lastname", "provider"] 转换为数组["John", "Smith", "gmail.com"]。然后将该数组与 apply 一起使用以调用 postional-argument 函数。

【讨论】:

  • 比我的解决方案更整洁。
  • 我希望有一个库可以处理它,我只是不想重新发明轮子。无论如何,您的解决方案针对我的需求;我在考虑更多:var argMapify = function(fn, argValues, context) { var argDefs = introspect(fn); return fn.apply(context, argDefs.map(function(arg) { return argValues[arg]; })); } 并调用 argMapify(fn, {...}),因为您从外部供应商处获取函数并即时调用函数。
  • 小心使用node-introspect,因为它将函数解析为字符串。任何超出其正则表达式的内容(在未来,我们有带有可选括号的 ES6 单参数箭头函数)将无法解析。简而言之,如果您在实际使用中考虑这一点,请小心。
【解决方案2】:

不使用任何外部库,

var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var ARGUMENT_NAMES = /([^\s,]+)/g;
function getParamNames(func) {
  var fnStr = func.toString().replace(STRIP_COMMENTS, '');
  var result = fnStr.slice(fnStr.indexOf('(')+1, fnStr.indexOf(')')).match(ARGUMENT_NAMES);
  if(result === null)
     result = [];
  return result;
}

function call(method, object) {
    var params = getParamNames(method);
    var arrParams = [];
    for (var i = 0; i < params.length; i++) {
        arrParams.push(object[params[i]]);
    }
    return method.apply(arrParams);
}

只需使用call(generateEmail, generateEmailObject) 调用它。

【讨论】:

    【解决方案3】:

    类似

       var orig_generateEmail = generateEmail;
       var generateEmail = function (map) {
                  orig_generateEmail(map.firstName, map.lastname, map.provider);
       };
    

    但这显然会出现在静态“映射”列表中。

    【讨论】:

      猜你喜欢
      • 2012-02-15
      • 1970-01-01
      • 1970-01-01
      • 2013-01-13
      • 1970-01-01
      • 2020-06-29
      • 2015-05-08
      • 2021-08-01
      • 2015-11-16
      相关资源
      最近更新 更多