写本篇博客的原因是发现有人遇到了以下误区,
1、在我面试别人的过程中,我想让他说一下数组的一些内置方法和含义,然后他条例思路不太清晰,跳动着说,所以遗漏了很多,或许按照es5到es6是一个指导顺序,或者先说对数组的删除,插入,再说到遍历这个顺序;
2、我问了一下filter,如果不用filter或者之前没有filter的时候,应该怎么实现一下filter的这个方法,貌似之前没有准备这块,其实也可能是filter用的不多;
3、我之前好像看过一篇博客,写的如果再用for循环,就要扇自己之类的,其实大可不必如此,我觉得我们之中很多人还没有强大到的鄙视某一项技术点的时候吧,想扇就扇自己几下吧,我们也看不见。
目录
1、filter 查找非 es6实现
2、every 判断的 非es6实现
3、some 判断的 非es6 实现
4、find查找的 非es6 实现
5、请为数组自定义一个方法 myFn ,实现 find 的方法
6、请说一说js中数组的常用内置方法
7、你现在遍历数组,还用for循环吗?
1、filter 查找非 es6实现
filter是通过遍历数组的所有元素,查找到符合过滤条件的元素,并且返回符合条件元素的集合。如果没有找到匹配的元素,那么返回的就是空数组,也就是返回的数组长度为0.代码如下:
var arr = [12, 33, 88, 66, 22];
var returnArr = arr.filter((item, index, arr) => {
console.log(index + ' 循环过程 ' + item);
return item > 50;
})
console.log('得到的returnArr::', returnArr);
非ES6的实现,代码如下:
var returnArr = [];
for (var i=0;i<arr.length;i++) {
if (arr[i] > 50) {
returnArr.push(arr[i]);
}
}
console.log(returnArr);
可以看出,filter相当于重新定义了一个空数组,对原数组进行了一次完整的遍历。需要注意的是filter是一次完整的遍历,数组长度是多少就要执行多少次,如果不是这种场景,可以考虑其他的执行方法。
2、every 判断的 非es6实现
every是对原数组进行遍历判断,every更强调每一个,遍历执行过程中,一旦某一个不符合过滤判断条件,将会直接跳出循环,不再继续执行循环,返回值是false,所以,every返回的是boolean值,代码如下:
var arr = [12, 33, 88, 66, 22];
var returnPause = arr.every((item, index, arr) => {
console.log(index + ' 循环过程 ' + item);
return item > 50;
})
console.log('得到的returnPause::', returnPause);
可见every是一个返回boolean值得执行过程,而且他强调每一个是否符合判断条件。
非ES6的实现,代码如下:
var returnPause = true;
for (var i=0;i<arr.length;i++) {
console.log(i);
if (arr[i] <= 50) {
returnPause = false;
break;
}
}
console.log(returnPause);
而非es6的实现明显判断条件和every的判断条件正好相反,同时every对for循环的break及时跳出循环做了一层封装。
3、some 判断的 非es6 实现
some和every更强调如果有,就返回true,及时跳出,不再继续执行循环。这里也是对break的一个封装。可以说在日常工作中,数组的元素可能非常多,如果不能及时做出break跳出,将会非常耗费性能。some的代码如下:
var arr = [12, 33, 88, 66, 22];
var returnPause = arr.some((item, index, arr) => {
console.log(index + ' 循环过程 ' + item);
return item > 50;
})
console.log('得到的returnPause::', returnPause);
而非es6的实现代码如下:
var returnPause = false;
for (var i=0;i<arr.length;i++) {
console.log(i);
if (arr[i] > 50) {
returnPause = true;
break;
}
}
console.log(returnPause);
与every相反,这里提前定义的返回结果为false,而some的提前定义结果为true。
4、find查找的 非es6 实现
find强调查找到的第一个元素,一旦找到符合条件的元素,将会跳出循环,不再继续执行,代码如下:
var arr = [12, 33, 88, 66, 22];
var returnArr = arr.find((item, index, arr) => {
console.log(index + ' 循环过程 ' + item);
return item > 50;
})
console.log('得到的returnArr::', returnArr);
可见,find查找也是找到后及时跳出循环,并且他返回的是某个元素,而非一个集合。
非es6的实现:
var returnItem = 0;
for (var i=0;i<arr.length;i++) {
console.log(i);
if (arr[i] > 50) {
returnItem = arr[i];
break;
}
}
console.log(returnItem);
以上4种查找方式更符合非准确查找案例,我们已知的是一个不太准确的消息,例如众多元素中是否有符合某种条件的元素存在,而非准确的说众多元素中是否有谁谁谁必须考了88分钟这样。
5、请为数组自定义一个方法 myFn ,实现 find 的方法
面试的时候,让当场自定义一个方法,去实现一些es6中新的方法,也是很常见的一种案例。上面我们已经知道了find的作用和他的本质实现,现在来自定义一个myFn,用来实现和find相同的需求逻辑,代码如下:
Array.prototype.myFn = function() {
var myArr = this;
var returnItem = 0;
for (var i=0;i<myArr.length;i++) {
if (myArr[i] > 50) {
returnItem = myArr[i];
break;
}
}
return returnItem;
}
var returnValue = arr.myFn();
console.log('所得结果::', returnValue);
面试的时候,可能面试官知道你练习过怎么自定义一个方法,他其实是在看你有没有注意break关键字的使用。
6、请说一说js中数组的常用内置方法
我建议你可以这样回答:
在日常工作之余呢,我也有总结过,因为他的内置方法太多了,很容易记混;
△ 首先,有对数组删除和插入操作的,例如
push(向尾部添加元素) | 这个方法返回的是新数组的长度 |
pop(删除数组尾部的一个元素) | 这个方法返回的是删除的元素 |
unshift(向数组开头添加元素) | 这个方法返回的是新数组的长度 |
shift(删除数组的第一个元素) | 这个方法返回的是删除的元素 |
splice(从数组的某个位置删除元素,还可以选择是否添加元素,添加几个) | 这个方法没有返回值,只是单纯的操作数组 |
concat(链接2个或者更多的数组) | 这个方法现在我比较习惯用es6的解构...来添加了 |
△ 非常常用的转字符串的方法,例如
toString方法 | 这个方法可以将数组转为字符串,相当于join方法没有入参 |
join | 这个方法可以按照一定的规则将数组转为字符串 |
△ 然后是返回数组的元素索引和截取
indexOf | 和字符串的方法类似,返回某个元素的第一次出现的索引值 |
lastIndexOf | 这个方法和indexOf相反,是返回最后一次出现的索引值 |
slice截取 | 知道了indexOf方法后,就可以对数组进行一定的截取工作,所以我把这2个方法放在一起记忆 |
△ 数组的循环和判断
for循环并不是数组的内置方法 | 但很多时候我还是比较喜欢这个方法的,因为很多新的方法其实封装了for循环 |
forEach循环 | 但其实forEach并不能实现break和continue,这是我不太喜欢的,如果不需要这2个的需求逻辑,我会用forEach循环 |
some和every | 这2个方法都是合理利用break的体现 |
filter过滤 | 这个方法会按照过滤条件,将循环整体走一遍,最后返回的是一个数组集合 |
find查找 | 这个方法最终找到第一个符合条件的元素就break了,返回的是一个元素 |
△ 比较常用的还有累积计算的方法
reduce方法 | 这个方法是将元素累积做计算,例如累加 |
可以说数组的内置方法还是比较多的,比较乱套。所以,不做一次整理,一旦面试的时候问起来很容易回答的很乱套,一旦乱套了,自己知道的东西也就忘记了。
7、你现在遍历数组,还用for循环吗?
回答:用,很多人觉得for循环很low,不应该再用for循环了,其实我还远没有达到鄙视某个知识点的地步。如果某个需求涉及到对数组整体进行一次遍历,那么我会用forEach来遍历,但如果涉及到查找某到某一个元素就要及时跳出,我还是会采用for循环加break关键字的。
虽然some和every有时候也能满足,但我觉得他们也是对for循环的一个封装,不如for循环本身实现快速。而且for循环的兼容性更好一些。