使用apply

时间:2017-09-17 00:00:24

标签: javascript arguments prototype apply higher-order-functions

我正在练习更高阶的功能,实际上是对引擎盖下的内容进行硬编码。我对这些问题感到困惑,因为我对apply()和arguments的工作原理知之甚少。

这是我的预期结果:

mapN([1, 2, 3], [4, 5, 6], [2, 2, 2], function(a, b, c) {
  return (a * b) + c;
});
// => [6, 12, 20]

mapN([1, 2, 3], function(x) { return x * x; }) // => [1, 4, 9]

我手动编写了一个forEach函数和一个这样的Map函数(我知道这不是必要的,但我试图真正了解HOF引擎盖下的内容):

function each(coll, f) {
  if (Array.isArray(coll)) {
    for (var i = 0; i < coll.length; i++) {
      f(coll[i], i);
    }
  } else {
    for (var key in coll) {
      f(coll[key], key);
    }
  }
}

function map(array, f) {
  var acc = [];
  each(array, function(element, i) {
    acc.push(f(element, i));
  });
  return acc;
}

但是,我不知道从哪里开始。我如何一起使用apply和arguments?我花了一个小时试图搞清楚吗? :

function mapN(f){
  var newArray = [];
  var args = Array.prototype.slice.apply(arguments);
  f.apply(newArray, args)
  return newArray;
}

1 个答案:

答案 0 :(得分:1)

您应遍历所有数组以生成将用于apply的参数数组:

function mapN () {
    var args = Array.from(arguments),                         // arguments passed to `mapN`
        callback = args.pop(),                                // the callback function is the last argument
        result = [];                                          // the result array

    if(!args.length) return result;                           // if there is no arrays passed as arguments, then return the empty array

    for(var i = 0, len = args[0].length; i < len; i++) {      // for each i from 0 to the length of one of the arrays
        var params = args.map(arr => arr[i]);                 // get the i-th element of every array in args to use as parameters to the callback
        result.push(callback.apply(null, params));            // call the callback with the params array and store the result
    }
    return result;
}

注意:如果数组的长度不同,那么您可能想要更改:

len = args[0].length

为:

len = Math.max.apply(null, args.map(arr => arr.length));

所以len将等于可能的最大长度。

<强>示例:

function mapN () {
    var args = Array.from(arguments),
        callback = args.pop(),
        result = [];

    if(!args.length) return result;

    for(var i = 0, len = args[0].length; i < len; i++) {
        var params = args.map(arr => arr[i]);
        result.push(callback.apply(null, params));
    }
    return result;
}

var a = mapN([1, 2, 3], [4, 5, 6], [2, 2, 2], function(a, b, c) {
    return (a * b) + c;
});
console.log(a);
// => [6, 12, 20]

var b = mapN([1, 2, 3], function(x) { return x * x; });
console.log(b);
// => [1, 4, 9]