关于一个闭包的问题

在廖雪峰博客上看到讲闭包这一节的知识,最后脑洞大开那一块的代码没有搞懂,代码如下:

'use strict';

// 定义数字0:
var zero = function (f) {
    return function (x) {
        return x;
    }
};

// 定义数字1:
var one = function (f) {
    return function (x) {
        return f(x);
    }
};

// 定义加法:
function add(n, m) {
    return function (f) {
        return function (x) {
            return m(f)(n(f)(x));
        }
    }
}

闭包
这是原文链接,有谁能讲解下他那个add()的逻辑,到底是怎样子的?

阅读 2.7k
2 个回答
var zero = function (f) {
    return function (x) {
        return x;
    }
};

这个东西调用两次能返回一个结果,zero(f)(x) = x,结果和f无关,和x有关。我们声明一个变量

var x = 0;

有了 zero(f)(x) === 0

var one = function (f) {
    return function (x) {
        return f(x);
    }
};

同样one(f)(x) = f(x)结果和f有关,f(x) === 1,我们定义一个f函数,让他满足这一点。

var f = function(x){
    return x + 1;
}

有了one(f)(x) === 1

function add(n, m) {
    return function (f) {
        return function (x) {
            return m(f)(n(f)(x));
        }
    }
}

根据这个可以得到

var two = add(one,one) = function(f){
    return function(x){
        return one(f)(one(f)(x));
    }
}

two(f)(x) = one(f)(one(f)(x)) = one(f)(1) = f(1) = 2

var three = add(two,one) = function(f){
    return function(x){
        return one(f)(two(f)(x));
    }
}

three(f)(x) = one(f)(two(f)(x)) = one(f)(2) = 3

...

把整个过程以代码和注释的形式解析并运行了,看看是否能够给你提供帮助:

one和f的定义:

// 定义数字1:
var one = function (f) {
    return function (x) {
        return f(x);
    }
};

function f (x) {
  console.log(x);
  return x;
}

add的定义和解释:

// 定义加法:
function add(n, m) {
    return function (f) {
        return function (x) {
            /*
             * 以add(one, one)为例解释我的理解:
             * two = add(one, one);
             * two的函数原型为: one(f)(one(f)(x))
             * 那么现在假设有一个function f,它长这样:
             * function f(x) {
             *   console.log(x);
             *   return x;
             * }
             * 则(two(f))(5)的执行为:one(f)(one(f)(5))
             * 而one的定义为:
             * var one = function (f) {
             *   return function (x) {
             *     return f(x);
             * };
             * 最终的执行为:
             * 1. 5  // console.log(5);
             * 2. one(f)(5)
             * 3. 5  // console.log(5);
             */
            return m(f)(n(f)(x));
        }
    }
}

调用执行:

var two = add(one, one);


one(f)(one(f)(5));

console.log('---------------');

(two(f))(5); // or two(f)(5);

结果:

5
5
---------------
5
5
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题