JavaScript 函数参数:位置 -> 地图转换

JavaScript function arguments: positional -> map transition

我正在寻找 普通 JavaScript 解决方案。

假设我有一个具有以下内容的函数 header:

generateEmail(firstName, lastname, provider)

我需要 运行 像这样:

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

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

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

而且我正在 JavaScript 中寻找 already-written 解决方案来执行此操作,因为我有无限数量的函数,例如 generateEmail 以上来处理。有这样的库吗?

我看过 https://github.com/kilianc/node-introspect 处理函数内省(返回函数抽象参数信息)。但是缺少第二部分 - 将 map-call 映射到 positional-call.

请问有没有这种东西


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

类似

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

但这显然以静态 "mappings".

列表结尾

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

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

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

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

不使用任何外部库,

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)调用即可。