首页 > 解决方案 > 如何理解这个高阶函数闭包发生了什么

问题描述

我知道我下面的代码是错误的,但显然我缺少一些信息。我必须编写更复杂的高阶函数,但如果我不能真正理解简单的函数,我就没有机会了。

hof.add 应该返回传递的两个参数的总和。很简单...但是鉴于我要创建这个高阶函数必须使用闭包。


    hof.add = function(add) {
      function makeAdd(a, b) {
        return add(a + b);
      }
      return makeAdd;
    };

it('returns total of the two arguments', () => {
        expect(hof.add(56, 5)).to.be.equal(56 + 5);
        expect(hof.add(91, -71)).to.be.equal(91 + -71);
      });

(建立在上面的框架)

hof.add = function() { };

标签: javascriptclosureshigher-order-functions

解决方案


如果您只想使用一个参数名称,也许您打算解构它:function(...add)

const not_hof = {};

// Cheating by using destructuring (...add) 
// and not a HOF since accepts only Numbers as arguments 
not_hof.add = function(...add) {  
  const makeAdd = add.reduce((prev, curr) => {
    return prev + curr;
  }, 0);
  return makeAdd; // and still not a HOF since it returns a Number 
};

console.log(not_hof.add(2, 3));              // 5
console.log(not_hof.add(9, 1, 10));          // 20
console.log(not_hof.add(1, 1, 1, 1, 1, 1));  // 6

PS:上面的函数也可以表示为:

not_hof.add = (...add) => add.reduce((prev, curr) =>  prev + curr, 0);

不是 HOF(高阶函数)

虽然很多人会说上面是一个高阶函数——因为它返回Array.prototype.reduce,它实际上不是

维基百科 - 高阶函数

在数学和计算机科学中,高阶函数是至少执行以下操作之一的函数:

  • 将一个或多个函数作为参数(即过程参数),
  • 返回一个函数作为其结果。

Butadd不是程序函数参数;IE:

过程 P(f):
 <em>返回 f(2,3) * f(9,1)

它不返回函数;而是由 .返回数字Array.prototype.reduce

1. HOF - 一个或多个函数作为参数

至少将函数作为参数传递

const helper = { // Helper functions
  add(a, b) { return  Number(a) + Number(b); },
};


const hof = {};
hof.add = function(fn, add1, add2) { // HOF since it takes a function as argument
  return fn(add1, add2);             // (Returns a Number)
};

// ...But it takes three arguments
console.log(hof.add(helper.add, 56, 5)); // 61

2. HOF - 返回一个函数

至少返回一个函数

const hof = {};

hof.add = function(add) { // (Takes a Number argument)
  function makeAdd(b) {
    return add + b;
  }
  return makeAdd;         // HOF since it returns a function
};

// But accepts a single argument at each call
console.log(hof.add(56)(5)); // 61

或喜欢

const hof = {};
hof.add = function(add1, add2) { // NOT LIKE YOUR EXAMPLE, 2 arguments are expected!
  function makeAdd() {
    return add1 + add2;
  }
  return makeAdd; // HOF since it returns a function
};

// ...The function had to be executed ()
console.log(hof.add(56, 5)());     // 61

但在这种情况下,它会失败您的测试说明:

it('returns total of the two arguments', () => { // nope :( only one argument here...

带闭合的 HOF

允许使用 a 多次调用函数Function.prototype.toString(),以便在最后一次调用时返回字符串

const hof = {};

hof.add = function(add) {
  let sum = add;    // Store in local scope
  const makeAdd = (b) => {
    sum += b;       // Access to lexical environment variables
    return makeAdd; // Returns a function (self)  
  }
  makeAdd.toString = () => sum;
  return makeAdd;   // HOF since we return a function
}

const result = hof.add(1)(2)(2)(56);
console.log(result)         // (f) 61
console.log(typeof result); // function
console.log(result == 61)   // true
console.log(result === 61)  // false
// A legitimate test might break since the strict equality operator fails.

让我们保持简单。没有关闭,没有 HOF

如果不需要使用 Array 解构和 Array.prototype.reduce() 的第一个示例,则只需坚持最简单的函数声明形式:

const not_hof = {
  add: (a, b) => a + b,
  sub: (a, b) => a - b,
  // etc...
};

console.log(  not_hof.add(56, 5)  ); // 61


推荐阅读