递归实现函数减少javascript

时间:2018-01-22 12:25:50

标签: javascript recursion reduce

我想写一个递归版的reduce函数。

Array.prototype.reduce2 =
function reduce(fn, initial) {
  var head = this[0];
  var tail = this.slice(1);
  var result = fn(initial, head, 0, tail);
  return reduce(tail, fn, result);
}

var a = [1, 2, 3, 4];

function add(a, b) { return a + b }  ;
function mul(a, b) { return a * b }  ;
function foo(a, b) { return a.concat(b) };

console.log(a.reduce(add), a.reduce2(add));                       // 10 10
console.log(a.reduce(add, 10), a.reduce2(add, 10)) ;              // 20 20
console.log(a.reduce(add, undefined), a.reduce2(add, undefined)); // NaN NaN
console.log(a.reduce(mul), a.reduce2(mul));                       // 24 24
console.log(a.reduce(foo, ''), a.reduce2(foo, ''));               // 1234 123

结果是:

10 [Function: add]
20 [Function: add]
NaN [Function: add]
24 [Function: mul]
1234 function foo(a, b) { return a.concat(b) }

是的,我知道这似乎有很多主题,但我找不到答案。

1 个答案:

答案 0 :(得分:1)

您应该避免向本机对象添加方法。

您可以使用参数的解构以更简单的方式使用简单函数执行相同的操作。

function reduce(fn, initial, [head, ...tail]) {
  return tail.length
    ? reduce(fn, fn(initial, head), tail)
    : fn(initial, head)
}

Array.prototype.reduce2 = function(fn, initial) {
  const head = this[0]
  const tail = Array.prototype.slice.call(this, 1)
  return tail.length
    ? tail.reduce2(fn, fn(initial, head))
    : fn(initial, head)
}

const a = [1, 2, 3, 4];

const add = (a, b) => a + b
const mul = (a, b) => a * b
const foo = (a, b) => a.concat(b)

console.log(
  reduce(add, 0, a),
  a.reduce(add, 0),
  a.reduce2(add, 0)
)

console.log(
  reduce(mul, 1, a),
  a.reduce(mul, 1),
  a.reduce2(mul, 1)
)

console.log(
  reduce(foo, '', a),
  a.reduce(foo, ''),
  a.reduce2(foo, '')
)

console.assert(
  a.reduce2(add, 0) === 10,
  'reduce2 can sum numbers'
)
console.assert(
  a.reduce2(mul, 1) === 24,
  'reduce2 can multiply numbers'
)
console.assert(
  a.reduce2(foo, '') === '1234',
  'reduce2 can contatinate strings'
)
<script src="https://codepen.io/synthet1c/pen/KyQQmL.js?tab=assert"></script>