JavaScrip实现计数器的多种方法

总结一下 JavaScript 实现计数器的几种方法,对于写出高性能代码有一定的帮助,同时也包含一些蛇皮操作。

普通写法

JavaScript
1
2
3
4
5
var counter = 0;
function countUp() {
return ++counter;
}
countUp();

创建一个全局变量counter,每次调用countUp()都会使counter的值+ 1,但是我们都知道无论是用何种语言写代码,都应该尽量使用少的全局变量,于是就有了下面这种经典写法。

使用闭包

JavaScript
1
2
3
4
5
6
7
const countUp = (() => {
let count = 0;
return () => {
return ++count;
};
})();
countUp();

这种写法能使用更少的全局变量,但闭包终归有闭包的缺点,它不会被垃圾回收机制处理,同时也不能像上一种写法那样重置counter,于是就有了下面这种写法。

使用函数属性

JavaScript
1
2
3
4
5
const countUp = () => {
return countUp.count++;
};
countUp.counter = 1;
countUp();

在 JavaScript 中函数是一种特殊的对象,既然是对象,那他自然也有属性,我们定义一个函数来操作它的counter属性。这种写法很好的解决了上面三个问题:

  1. 解决闭包的内存占用
  2. 可以重置counter
  3. 尽量少的全局变量

如果你会TypeScript,那么通过下面这个例子你能更好的理解函数属性。

JavaScript
1
2
3
4
interface CountUp {
(): number;
counter: number;
}

上面这段代码定义了一个函数接口,这个函数拥有 0 个参数,返回值是一个number类型的值,并且有counter属性。

让我们看看最后一种写法,这种写法没有任何优势,甚至是大材小用的写法。

Generator

JavaScript
1
2
3
4
5
6
7
8
9
10
11
const counter = (function* Counter() {
let count = 0;
while (true) {
count++;
yield console.log(count);
}
})();

function countUp() {
return counter.next();
}

在这里,我们使用了一个无限迭代器来实现,通过使用counter.next()来手动使迭代器迭代,个人认为这种写法比使用闭包的开销还要大,用作计数器实在是大材小用了。迭代器在 ES6 之前就被实现了,在 ES6 中才正式成为规范,它在 JavaScript 的作用通常是用来构建异步函数(async/await)。

虽然最后这种写法没有什么实质性的作用,但对于理解迭代器还是有帮助的,另外,有些厂笔试就喜欢出这种花里胡哨的题。

评论

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×