使用JavaScript的Array高阶函数代替for循环
有什么不明白的地方,扫描右方二维码加我微信交流。
昨天看了一篇文章,叫做《如何在 JS 代码中消灭 for 循环》,学习到了新的代码编写思路,在这里记录一下。文章中使用到的方法多为JS中的高阶函数和ES6的一些新特性,理解文章中的每个知识点需要我熟练使用高阶函数并熟悉ES6的新特性。由此这想到,想要把代码写的优雅,简略,必须多了解一些函数。像map,filter这样的方法,可以减少代码量,提升工作效率。所以把一些使用率较高的方法整理在下面。
高阶函数并不是说运行效率很高,而是用法很高级,底层的实现依然是循环机制。
=>(箭头函数)
ES6标准新增了一种新的函数:Arrow Function(箭头函数)。
x => x * x; //相当于 function (x) { return x * x; }
filter(筛选、过滤函数)
现有数组:
let testArr = [3, 4, 5, 2, 3, undefined, null, 0, '', 'A', 'B', 'C', 3];
过滤掉数组中的number类型数据,代码如下:
let testA = testArr.filter(element => typeof(element) !== 'number');
过滤掉数组中的为假的数据:
let testB = testArr.filter(Boolean);
运行结果:
console.log(testA); console.log(testB); [ undefined, null, '', 'A', 'B', 'C' ] [ 3, 4, 5, 2, 3, 'A', 'B', 'C', 3 ]
去除重复元素方法1:
//element每个元素值,index是索引值,self是arr自身 let testC = testArr.filter(function (element, index, self) { return self.indexOf(element) === index; });
去除重复元素方法2,ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值:
let uniq = arr => [...new Set(arr)];
运行结果:
console.log(testC); console.log(uniq(testArr)); [ 3, 4, 5, 2, undefined, null, 0, '', 'A', 'B', 'C' ] [ 3, 4, 5, 2, undefined, null, 0, '', 'A', 'B', 'C' ]
map,forEach(遍历)
有如下数组(这个数组的子元素是引用型数据):
let usersArr = [ {name: 'tom1', age: 10}, {name: 'tom2', age: 18}, {name: 'tom3', age: 20}, {name: 'tom4', age: 5}, ];
给18岁以下的人添加一个isChild属性,并赋值true:
usersArr.map(element => element.age < 18 ? {...element, isChild: element.isChild = true} : element; );
或者
usersArr.forEach(element => element.age < 18 ? {...element, isChild: element.isChild = true} : element; );
运行结果:
console.log(usersArr); [ { name: 'tom1', age: 10, isChild: true }, { name: 'tom2', age: 18 }, { name: 'tom3', age: 20 }, { name: 'tom3', age: 5, isChild: true } ]
注意1:以上的usersArr发生了改变是因为usersArr的子元素为object数据类型,即element有引用关系,修改element就是修改usersArr的子元素本身。如果是常量型的数据呢,如下:
let usersArr2 = [ 'tom1', 'tom2', 'tom3', 'tom4', ]; let copy1 = usersArr2.map(element => element + '_test' ); let copy2 = usersArr2.forEach(element => element + '_text' ) console.log(usersArr2); console.log(copy1); console.log(copy2);
运行结果:
[ 'tom1', 'tom2', 'tom3', 'tom4' ] [ 'tom1_test', 'tom2_test', 'tom3_test', 'tom4_test' ] undefined
可以看到,usersArr2未发生改变,copy1发生改变,copy2为undefined。
注意2:forEach方法不会返回任何数据,map会生成一个新的arr返回。
every,some,find,includes,from(判断每个是否满足某个条件,判断某个是否满足条件,查找,包含,浅拷贝生成一个新数组)
判断是否全是成年人:
console.log(usersArr.every(user => user.age >= 18));
判断是否有未成年人:
console.log(usersArr.some(user => user.age < 18));
找出第一个未成年人:
console.log(usersArr.find(user => user.age < 18));
运行结果:
false true { name: 'tom1', age: 10, isChild: true }
判断是否存在原音字母:
let randomStr = 'alsdjfpuqwerlkjsdfj'; let containsVowel = str => [...str].some(char => ['a', 'e', 'i', 'o', 'u'].includes(char)); console.log(containsVowel(randomStr));
运行结果:
true
字符串转数组,生成新数组,生成100以内的随机数10个:
console.log(Array.from('foo')); console.log(Array.from([1, 2, 3], x => x + x)); console.log(Array.from({length: 10}, _ => Math.floor(Math.random() * 100)));
运行结果:
[ 'f', 'o', 'o' ] [ 2, 4, 6 ] [ 61, 9, 31, 92, 95, 74, 74, 15, 79, 10 ]
sort(排序)
如果对一个数组进行排序,最常用的就是冒泡排序了,但是写起来很麻烦,使用sort方法能很方便的排序,如下数组:
var names = ['Google', 'apple', 'Microsoft']; names.sort(); console.log(names); var array1 = [1, 30, 4, 21]; array1.sort(); console.log(array1);
运行结果:
[ 'Google', 'Microsoft', 'apple' ] [1, 21, 30, 4]
注意:sort方法默认把所有元素先转换为String再排序,因为字符’2’比字符’4’的ASCII码小,所以21在4前。G和M在小写字母a之前同理。
如果想要得到预想中的排序,则需要让sort方法接收一个比较函数:
names.sort(function (s1, s2) { let x1 = s1.toUpperCase(); let x2 = s2.toUpperCase(); if (x1 < x2) { return -1; } if (x1 > x2) { return 1; } return 0; });
array1.sort(function (x, y) { if (x < y) { return -1; } if (x > y) { return 1; } return 0; });
运行结果:
[ 'apple', 'Google', 'Microsoft' ] [ 1, 4, 21, 30 ]
以上是我觉得在可以替代工作中的一些for循环的使用,Array还有很多其它方法,都很简单,就不在这造轮子了,想要学习的同学点击链接学习。
有什么问题可以在下方留言。