马黑黑 发表于 2025-11-22 12:32

JS极简闭包计数器

<style>
        .artBox { font-size: 18px; margin: 20px auto; max-width: 1200px; }
        .artBox > p { margin: 10px 0; line-height: 30px; }
        .artBox mark { padding: 4px 6px; background: lightblue; }
</style>

<div class="artBox">
        <p>函数就一行代码:</p>
        <div class="codebox">const counter = (startNum) => () => ++startNum;</div>
        <p>这是箭头函数的好处,简洁。但是,函数看着抽象,分行写看看:</p>
        <div class="codebox">
const counter = (startNum) => {
        return () => ++startNum;
};
        </div>
        <p>还有点抽象?箭头函数的问题。用传统函数改写一下:</p>
        <div class="codebox">
function counter(startNum) {
        return function() {
                return ++startNum;
        }
}
        </div>
        <p>如果确实不习惯箭头函数,现在也应该可以看出点道道来了:这是一个函数里还有函数的函数。外层函数是具名函数,counter,计数器,它需要一个参数,startNum,起始计数值;里层函数被外层函数嵌套,是个匿名函数,它将外层函数的参数 startNum 加 1 并返回结果,然后以函数形式返回给外层函数。</p>
        <p>外层函数称父函数,里层的函数称子函数。子函数通常就是一个闭包,它能获取父层函数的参数或变量并对之操作,然后,或者返回操作结果,或者返回函数。本例返回的是函数,所以,这样调用:</p>
        <div class="codebox" data-prev="1">
&lt;style&gt;
        .counterWrap { padding: 40px; }
        #txtRes, #btnAdd { margin: 0; padding: 8px; }
&lt;/style&gt;

&lt;div class="counterWrap" style=""&gt;
        &lt;input type="text" id="txtRes" value="0" /&gt;
        &lt;button type="button" id="btnAdd"&gt;点击计数&lt;/button&gt;
&lt;/div&gt;

&lt;script&gt;
        // 闭包计数器
        const counter = (startNum) =&gt; () =&gt; ++startNum;
        // 引用函数
        const calc = counter(0);
        // 输出结果
        btnAdd.onclick = () =&gt; txtRes.value = calc();
&lt;/script&gt;
        </div>
</div>

<script type="module">
        import linenumber from 'https://638183.freep.cn/638183/web/js/linenumber.js';
        linenumber();
</script>

马黑黑 发表于 2025-11-22 12:38

counter 函数返回的是函数,不能直接得到结果,所以创建一个引用 counter 函数 的函数 calc:

constcalc = counter(0);

这个 calc() 函数才是直接拿到结果的函数。可以根据需要创建初始值不同的计数器,例如从10开始:

const calc10 = counter(10);

首次calc10() 运行的结果是 11 ,而后以 1 为单位继续累加

马黑黑 发表于 2025-11-22 12:43

闭包计数器函数属于纯函数,它不改变外部变量,只根据参数进行运算,同时将运算结果储存在闭包里面,外部只能使用它而无法改变它

红影 发表于 2025-11-22 15:37

这个是从0开始的,每点击一下,就累积一次呢{:4_187:}

红影 发表于 2025-11-22 15:39

这个步距永远是1吧,不能以2为单位进行累加吧{:4_173:}

马黑黑 发表于 2025-11-22 17:40

红影 发表于 2025-11-22 15:39
这个步距永远是1吧,不能以2为单位进行累加吧

++变量

等于

1+变量

1 是累加数

如果需要不同的累加数,需要修改 counter 函数

马黑黑 发表于 2025-11-22 17:41

红影 发表于 2025-11-22 15:37
这个是从0开始的,每点击一下,就累积一次呢

对,后续创建的 calc 函数以 counter(0) 调用计数器函数,0 是计数器的起始值

红影 发表于 2025-11-22 20:35

马黑黑 发表于 2025-11-22 17:40
++变量

等于


大多数都采用1作为累加数的吧。

红影 发表于 2025-11-22 20:36

马黑黑 发表于 2025-11-22 17:41
对,后续创建的 calc 函数以 counter(0) 调用计数器函数,0 是计数器的起始值

我在那个演示里给了它一个数,结果它还是一点点加起来的,如果需要改变从0开始,是代码里改变的呢。

马黑黑 发表于 2025-11-22 22:18

红影 发表于 2025-11-22 20:36
我在那个演示里给了它一个数,结果它还是一点点加起来的,如果需要改变从0开始,是代码里改变的呢。

counter 是一个函数工厂,它可以创建:

counter calc_from(0) = counter(0); // 从0开始计数
const calc_from(5) = counter(5); // 从5开始计数

运行上述两个函数,每一次都是加1,第一个第一次函数运行得到1,然后就是2、3、4、5……;第二个函数第一次运行的6,然后就是7、8、9、10……

马黑黑 发表于 2025-11-22 22:19

红影 发表于 2025-11-22 20:35
大多数都采用1作为累加数的吧。

这个看需要,不同的需要做不同的函数设计
页: [1]
查看完整版本: JS极简闭包计数器