通过计数器和函数工厂,理解闭包

通过简单的例子来理解闭包的概念和作用

Posted by Suzulang on March 22, 2024
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
<script>
function createCounter() {
    let count = 0;
    

    return {
        increament : function() {
          count++;  
        },
        reset: function() {
            count = 0;
        },
        getCount: function() {
            return count;
        },
        name: "计数器"
    };
}

const counter1 = createCounter();
const counter2 = createCounter();
counter1.increament();
counter1.increament();
console.log(counter1.getCount()); // 输出 2
console.log(counter2.getCount()); // 输出 0
counter2.increament();
console.log(counter2.getCount()); // 输出 1
counter1.reset();
console.log(counter1.getCount()); // 输出 0
console.log(counter1.name);
</script>
</body>
</html>

这里创建了一个函数工厂createCounter,并且将函数作为值赋给了两个变量。这两个变量就拥有的私有的数据,互不影响。

这就是闭包。

在javascript中在语法层面支持了闭包。

在java中,想实现同样的效果的话,可以通过lambda表达式

import java.util.function.IntSupplier;
public class Counter {
    public static void main(String[] args) {
        IntSupplier counter = counterSupplier();
        System.out.println(counter.getAsInt()); // 输出:0
        System.out.println(counter.getAsInt()); // 输出:1
        counter.getAsInt(); // 增加计数,但不打印
        System.out.println(counter.getAsInt()); // 输出:2
    }
    public static IntSupplier counterSupplier() {
        int[] count = new int[1]; // 使用数组来存储状态
        return () -> {
            count[0] += 1; // 每次调用时增加计数
            return count[0]; // 返回当前计数
        };
    }
}

java的实现,明显比js的代码更不容易懂。你需要补充了解一下函数式接口的知识,下面是IntSupplier接口的代码,可以看到这个接口定义了一个getAsInt方法,而js中是直接在返回的对象中,定义函数名,和函数实现代码。

package java.util.function;

@FunctionalInterface
public interface IntSupplier {

    /**
     * Gets a result.
     *
     * @return a result
     */
    int getAsInt();
}