不管是什么语言,你都需要在你的程序中对数据进行迭代或循环。在JavaScript中,我们有几个循环结构可以做到这一点,还有所谓的高阶函数。这些高阶函数允许使用更简洁的语法,允许你在一个集合上进行迭代,同时根据你的需要对集合中的每个项目应用你所选择的逻辑。它们有时有点棘手,所以我们将在本教程中练习大量的函数。我们将研究for、forEach、for of、for in、filter、map、sort和reduce。
我们需要一些数据
我们可以在一组简单的数据上进行练习。这里有一个对象数组和一个数字数组,我们将用它来练习。
// Array of objects
const companies = [
{ id: 1, name: "Square", sector: "Finance", founded: 2009 },
{ id: 2, name: "Disney", sector: "Media", founded: 1923 },
{ id: 3, name: "Ford", sector: "Auto", founded: 1903 },
{ id: 4, name: "Netflix", sector: "Media", founded: 1997 },
{ id: 5, name: "Apple", sector: "Technology", founded: 1976 },
{ id: 6, name: "Visa", sector: "Finance", founded: 1958 },
{ id: 7, name: "Tesla", sector: "Auto", founded: 2003 },
{ id: 8, name: "Microsoft", sector: "Technology", founded: 1975 },
{ id: 9, name: "Roku", sector: "Media", founded: 2002 }
];
// Array of numbers
const numbers = [32, 15, 20, 16, 52, 54, 11, 49, 31, 19, 75, 42, 45, 68, 30];
我们还将使用这个封装函数,这样我们就可以在浏览器窗口中看到结果,而不必手动打开控制台。
function output(data) {
document.write(data + "<br/>");
}
for
好了!现在让我们从一些基本的循环开始,这样我们就可以看到当我们进入高阶函数时,事情的运作会有一些不同。首先是基本的 **for**循环。我们想在所有的公司中进行循环并输出它们的名字。
for (let i = 0; i < companies.length; i++) {
output(companies[i].name);
}

forEach
为了做同样的事情 forEach做同样的事情,我们可以使用这种风格的代码。
companies.forEach(function(company) {
output(company.name);
});

for of
这个 for of循环将看起来像这样。
for (let company of companies) {
output(company.name);
}
for in
通过这个 **for in**循环,我们可以遍历一个对象的所有键值对。通过这段代码,我们遍历我们公司数组中第4个对象的属性。
for (let property in companies[3]) {
output(property + ": " + companies[3][property]);
}

过滤器
filter函数是我们可以看的第一个高阶函数。如果你写React代码,你会一直使用filter!这个函数是用来根据一个条件访问一个数组的子集。假设我们只想要我们的数字数组中小于或等于20的数字。在使用过滤器之前,我们必须使用这样一个for循环。
let twenty = [];
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] <= 20) {
twenty.push(numbers[i]);
}
}

使用 filter函数,我们可以实现同样的结果。
const twenty = numbers.filter(data => {
if (data <= 20) {
return true;
}
});

为了进一步简化这个过程,你可以使用这个简单的单行线
const twenty = numbers.filter(num => num <= 20);

现在让我们用公司的对象数组和过滤函数一起工作。假设我们只想输出金融行业的公司。没问题!
const financeCompanies = companies.filter(function(company) {
if (company.sector === "Finance") {
return true;
}
});
financeCompanies.forEach(data => output(data.name));

我们可以使用过滤函数来寻找在20世纪70年代成立的公司,就像这样。
const seventiesCompanies = companies.filter(
company => company.founded >= 1970 && company.founded < 1980
);
seventiesCompanies.forEach(company => output(company.name));
而看起来苹果和微软是在七十年代成立的。

请注意,我们给箭头函数的参数起的名字可以是任何我们想要的。大多数时候,你会使用一个对你有意义的命名规则,但作为一个例子,下面的代码产生的结果是完全一样的。
const seventiesCompanies = companies.filter(
tomato => tomato.founded >= 1970 && tomato.founded < 1980
);
seventiesCompanies.forEach(cucumber => output(cucumber.name));
这总是让我有点困惑,所以希望这个小提示能为你(和我)解惑。
这里是过滤功能的另一个例子,我们找到了经营40年以上的公司。这一切只需要一个简单的单行代码。(第二行代码只是为了在浏览器中显示结果)。
const fortyYears = companies.filter(company => 2019 - company.founded >= 40);
fortyYears.forEach(company => output(company.name));

就像我们前面提到的,你会用React的过滤函数,所以这是一个很好的练习。
地图
现在我们可以继续使用 map函数。那么,map函数为我们做了什么?map函数用于创建一个新的数组,该数组保存了对原数组中每个元素调用一个给定函数的结果。所以,你拿着一个数组,在每个元素上调用一个函数,从而填充一个新的数组。让我们看几个如何使用map函数的例子。
我们可以把每个公司的名字摘出来,比如说,把它放到一个新的数组中。
const newArray = companies.map(company => company.name);
newArray.forEach(company => output(company));

我们可以用map来运行一个函数,把公司的描述放到一个新的数组中,然后输出。
const description = companies.map(
company =>
`${company.name} was founded in ${company.founded} and is in the ${
company.sector
} business`
);
description.forEach(d => output(d));

一个使用map来迭代我们的数字数组中的所有数字的例子如何。这个例子将把数组中的每个数字设置为2的幂,结果存储在一个新的数组中,然后我们把结果输出给浏览器。
const powerTwo = numbers.map(num => Math.pow(num, 2));
powerTwo.forEach(num => output(num));

所以这些是使用map函数的几个例子。要在React中创建一个列表,你可以使用map函数。
排序
我们可以看一下的另一个高阶函数是排序函数。第一个例子将展示如何将公司从最早的到最新的进行排序。
const sortedCompanies = companies.sort(function(c1, c2) {
if (c1.founded > c2.founded) {
return 1;
} else {
return -1;
}
});
sortedCompanies.forEach(c => output(c.name));

你可以用这个更简洁的代码完成同样的结果,它使用了三元操作符,就像这样。
const sortedCompanies = companies.sort((c1, c2) =>
c1.founded > c2.founded ? 1 : -1
);
sortedCompanies.forEach(c => output(c.name));
将数字数组从最小到最大进行排序如何?可以用这个片段来完成。
const sortInts = numbers.sort((a, b) => a - b);
sortInts.forEach(n => output(n))
;

减少
这个 **reduce**函数是一个有趣的函数,它接收一个有许多值的数组,并将其减少到一个输出值。你经常看到这个函数用于把一个数组中的所有值加起来,然后输出这个值。我一直认为用reduce函数做加法有点奇怪,但可惜,事实就是如此。
举例来说。
let numSum = 0;
for (let i = 0; i < numbers.length; i++) {
numSum += numbers[i];
}
output(numSum);

你可以使用这个更优雅的解决方案来获得同样的结果。
const numSum = numbers.reduce((total, num) => total + num, 0);
现在让我们练习一下在公司对象的数组上使用reduce。这个工作方式有点不同,但概念是一样的。让我们把这些公司总共经营了多少年加起来。
const totalYears = companies.reduce(function(total, company) {
return total + (2019 - company.founded);
}, 0);
output(totalYears);

简短的版本也同样好用。
const totalYears = companies.reduce(
(total, company) => total + (2019 - company.founded),
0
);
高阶函数的一个有趣的方面是,你可以把它们串联起来,一次完成几个操作。在这里的例子中,我们将把我们的数字分别乘以3,然后只看那些数值大于或等于70的数字,最后从低到高进行排序。
const combined = numbers
.map(num => num * 3)
.filter(num => num >= 70)
.sort((a, b) => a - b);
combined.forEach(c => output(c));

JavaScript中的高阶函数摘要
在本教程中,我们了解了JavaScript中的一些高阶函数,如filter()、map()、sort()和reduce()。通过使用这些高阶函数,你可以减少你必须编写的 for通过使用这些高阶函数,你可以减少你必须编写的循环,使你能够创建更简洁和优雅的代码。此外,在Vue、React和Angular等流行框架中,经常需要这些类型的函数来转换或过滤数据,所以它们是你工具箱中的一项好技能。