本文完整阅读约需 11 分钟,如时间较长请考虑收藏后慢慢阅读~

『如何使用JavaScript判断一个值是否在一个数组中』一文里,我提到了使用Array.prototype.includes()Array.prototype.indexOf()两种方法来实现这一需求,但其实对于JavaScript这样一门极为灵活的语言来说,实现方法远不止以上两种。

如标题所示,本文主要提到的就是JavaScript中的迭代器。

0x01

在其他语言(例如Python)中,迭代器是List(Array)甚至Object数据类型中非常重要的一个Feature,可惜JavaScript直到ECMAScript 2015才给予迭代器以正式支持。

0x02

按照文档所示,迭代器的用法见以下代码:

for (each of array) {
    console.log(each);
}

即可以通过of关键词,实现对Array(以及其他可迭代对象,例如 MapSetStringTypedArray等)的迭代。

0x03

然而,正如上文所提到的那样,由于迭代器被引入语法规范的时间如此之短,导致我们在实际应用过程中,因为兼容性的考量很难放心大胆使用这个Feature。
好在微软的TypeScript早有考虑。这门语言是JavaScript的超集,为JavaScript开发引入了静态检查和编译机制,和Sass之于CSS的地位相同,但更强大。TypeScript的官方编译器实现不仅在TypeScript中加入了of迭代器的支持,而且支持将这一迭代器语法在编译过程中实现向下兼容!

  1. 这是TypeScript代码:
let someArray = [1, "string", false];
for (let entry of someArray) {
    console.log(entry); // 1, "string", false
}
  1. 这是以ES3和ES5为目标版本编译出的JS代码:
var someArray = [1, "string", false];
for (var _i = 0, someArray_1 = someArray; _i < someArray_1.length; _i++) {
    var entry = someArray_1[_i];
    console.log(entry); // 1, "string", false
}
  1. 这是以ES2015为目标版本编译出的JS代码:
let someArray = [1, "string", false];
for (let entry of someArray) {
    console.log(entry); // 1, "string", false
}

可以看到,ES2015目标版本和TypeScript实现完全一致,而如果要实现向下兼容,只需针对较低版本进行编译即可,这样可以同时保证开发的便捷性与较好的兼容性。

其实Babel也可以实现相同效果,但Babel专注于兼容,TypeScript专注于扩展语法和编译时的静态分析+警告,在日常使用中,后者更为强大。
小声BB:强大的东西不一定好,好的东西,TypeScript所实现的大量特性(如泛型、接口等)更适用于严谨的软件工业,而非学习、实验、玩耍,各位在学习TypeScript的时候千万不要被那么多的Feature给镇住,学自己需要的即可,其他的尽管等编译器报错的时候再去学习也不迟!

0x04

刚刚说了那么多关于迭代器的知识,那么如何使用迭代器来判断一个值是否在一个数组中呢?相信大家也一定心里有谱了。而对于那些遇到问题亟待解决,大叫着TL;DR点击本文链接的读者,代码如下:

  1. TypeScript版
let array: Number[] = [1, 2, 3, 4, 5];

// 避免类型检查不通过,对Array接口进行重载,增加inArray()方法
interface Array<T> {
    inArray(needle): boolean;
}

// 一行代码解决问题
Array.prototype.inArray = (needle: any): boolean => {for (let i of array) if (i === needle) return true; return false;};

console.log(array.inArray(1));      // true
console.log(array.inArray(12));     // false
  1. JavaScript版(ES2015 or Higher)
Array.prototype.inArray = (needle: any): boolean => {for (let i of array) if (i === needle) return true; return false;};

console.log(array.inArray(1));      // true
console.log(array.inArray(12));     // false
  1. JavaScript版(ES3 / 5)
Array.prototype.inArray = function (needle) { for (var _i = 0, _a = array; _i < _a.length; _i++) if (_a[_i] === needle) return true; return false; };

console.log(array.inArray(1));      // true
console.log(array.inArray(12));     // false