every
首先,我们要了解我们要手写的整个函数它的功能
every:依次遍历数组中的每项,当碰到一项不满足条件,则返回false,只有当全部符合条件时则返回true
array.every(function(currentValue,index,arr), thisValue)
var arr = [101, 12, 32, 2, 3, 44, 120, 3, 5];
// every 表示每一项都必须通过才会返回true
// every对每一个元素执行一个callback
// 直到它找到一个使 callback 返回 false的元素, 就返回false
// 直到遍历完成也没有返回false的话,就返回true
console.log(arr.every(i => { return i > 50 }))
// every 手写
Array.prototype.myevery = function (fn) {
if (typeof (fn) != 'function') {
throw new TypeError(`error ${fn} no a function`)
}
for (let i = 0; i < this.length; i++) {
// 对arr中项依次执行if语句
// 当碰到一项不满足>50则退出整个函数,不再执行执行下面的项
if (!fn(this[i])) {
return false;
}
}
return true
}
let my = arr.myevery(item => { return item > 50; })
console.log(my)
// function test() {
// for (let i = 0; i < 10; i++) {
// console.log(i)
// // 说明return false可以退出函数,不继续执行
// if (arr[i] < 50) {
// return false
// }
// }
// return 90
// }
// test()
// // console.log(test())
some
some:依次遍历数组的每一项,当遇到一项满足条件便返回true,不再继续后面的遍历,跟every作用正好相反
array.some(function(currentValue,index,arr),thisValue)
var arr = [1, 12, 32, 2, 3, 44, 120, 3, 5];
// 只要有一项满足就返回true,不再继续执行
// console.log(arr.some(item => { return item > 50 }))//true
//手写some
// fn是代表数组每一项要执行的函数,必须使用function不能使用箭头函数
Array.prototype.mysome = function (fn) {
if (typeof fn != 'function') {
console.log(`${fn} is not a function`)
return false
}
// this指向调用mysome函数的对象,即是arr
for (let i = 0; i < this.length; i++) {
if (fn(this[i])) {
// 只要有一项满足条件则跳出函数,不继续执行
return true
}
}
//当所有的都不满足条件时通过下面这个返回false,并跳出函数
return false
}
let my = arr.mysome(item => { return item > 50 });
console.log(my)//true
find
find的作用和some类似,都是当遇到一项满足条件便返回true,不再继续后面的遍历区别:find是返回满足条件的第一个值,some是当遇到满足条件的第一项时返回true
array.find(function(currentValue, index, arr),thisValue)
// 由于和some方法并没有区别,只是返回值有区别,在此不详细贴出代码
var arr = [1, 12, 32, 2, 3,120, 44, 3, 5];
// 只要有一项满足就返回该值,不再继续执行,否则返回undefind
console.log(arr.find(item => { return item > 50 }))//120
// 手写find
// 只要有一项满足条件则跳出函数,不继续执行
return this[i]
//当所有的都不满足条件时通过下面这个返回undefined,并跳出函数
return undefined
findIndex
findIndex是返回满足条件的第一个值的索引,find和findIndex和some方法类似,区别在于返回值不同。
find和findIndex在全部不满足条件时都返回undefined
array.findIndex(function(currentValue, index, arr), thisValue)
// 由于和find方法并没有区别,只是返回值有区别,在此不详细贴出代码
var arr = [1, 12, 32, 2, 3,120, 44, 3, 5];
// 只要有一项满足就返回该值,不再继续执行,否则返回undefind
console.log(arr.findIndex(item => { return item > 50 }))//5
// 手写findIndex
// 只要有一项满足条件则跳出函数,不继续执行
return i
//当所有的都不满足条件时通过下面这个返回undefined,并跳出函数
return undefined
includes
includes和findIndex这两个都可以用来查找数组中是否有某个元素,只是返回值有区别
includes() 方法用来判断一个数组是否包含一个指定的值,如果是返回 true,否则false。
在这里插入代码片
forEach
forEach 遍历数组全部元素,利用回调函数对数组进行操作
自动遍历数组数组元素个数次,且无法break,return 中途跳出循环,除非抛出异常
注意: forEach() 对于空数组是不会执行回调函数的。
// 对象数组
var arr = [{ name: 'kk', age: 90 }];
//forEach返回值是undefined, foreach不能通过return返回指定的返回值
console.log(arr.forEach(item => { item.age *= 2 }));//undefined
console.log(arr)//[ { name: 'kk', age: 92 } ]
// 普通数组
var arr = [1, 12, 32, 2, 3, 120, 44, 3, 5];
console.log(arr.forEach(item => { item *= 2 }));//undefined
// 数组无变化
console.log(arr)//[ 1, 12, 32, 2, 3, 120, 44, 3, 5 ]
为什么forEach对普通数组不产生作用呢?
主要在于数组里面每一项是引用数据类型还是基本数据类型
看完这篇链接文章,相信你一定会恍然大悟
forEach有两个参数
array.forEach(function(currentValue, index, arr), thisValue)
第二个参数thisValue可以设置回调函数中this的指向
JS forEach()第二个参数
forEach每次执行匿名函数都支持三个参数,参数分别为item(当前每一项),index(索引值),arr(原数组)
// forEach回调函数会跳过数组空元素
var obj = {}, count = 0;
function logArray(value, index, array) {
count++;
obj[count] = value;
}
[1, 2, , 4].forEach(logArray);
console.log(obj); // {1: 1, 2: 2, 3: 4}
console.log(count) // 3
var arr = [101, 12, 32, 2, 3, 44, 120, 3, 5];
var arr2 = [1,2,3,4,5,6];
var arr1 = {name:'kkk',age:50}
// 改变this的指向
arr.forEach(function (item) {console.log(this)},arr1)
//{ name: 'kkk', age: 50 }*arr.length
// 注意在箭头函数中引用this实际上是调用的是定义时的上一层作用域的this为window。
// js作用域:全局作用域、函数作用域、块级作用域(通过let,const声明的)
arr.forEach(item =>{console.log(this === window)}) //true*arr.length
arr.forEach(item => {console.log(this === window)},arr1) //true*arr.length
arr.forEach(item => {console.log(this === window)},this) //true*arr.length
了解了forEach的功能之后,我们就可以上手自己写一个forEach函数了
var arr = [1, 12, 32, 2, 3, 120, 44, 3, 5];
var arr2 = [1, 2, 3, 4]
// arr.forEach(function (item, index, arr) {
// console.log(item, index, this)
// }, arr2)
// 结果太长了,你们可以自己打印看看结果
Array.prototype.myforEach=function(fn,thisArg){
// this代表调用这个函数的数组
var _this = this
// 判断调用myforEach的对象是不是一个数组
if(!Array.isArray(this)){
console.log('not a array')
}
// 判断传入的是不是函数
if (typeof fn != 'function') {
console.log(`${fn} is not a function`)
return false
}
// 有传入第二个参数,改变fn的this指向
if(arguments.length > 1){
_this = thisArg;
}
// 对数组每一项执行该函数
for(let index = 0; index < this.length; index++){
fn.call(_this,this[index],index,this)
}
}
arr.myforEach(function(item,index,arr) {
console.log(item, index, this === window)
},arr2)
map
map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值
array.map(function(value, index, array))
var arr = [1, 12, 32, 2, 3, 120, 44, 3, 5];
var arr2 = [1, 2, 3, 4]
var arr3 = arr.map(function (item, index, arr) {
return item+index
})
console.log(arr3)
Array.prototype.myMap=function(fn){
// 判断调用myforEach的对象是不是一个数组
if(!Array.isArray(this)){
console.log('not a array')
}
// 判断传入的是不是函数
if (typeof fn != 'function') {
console.log(`${fn} is not a function`)
return false
}
// 对数组每一项执行该函数
let resArrary = []
for(let index = 0; index < this.length; index++){
resArrary.push(fn(this[index], index, this))
}
return resArrary
}
var arr3 = arr.myMap(function(item,index,arr) {
return index+item
})
console.log(arr3)
filter
返回满足条件的每一项到新数组
var arr = [1, 12, 32, 2, 3, 120, 44, 3, 5];
var arr2 = [1, 2, 3, 4]
var arr3 = arr.filter(function (item, index, arr) {
return item+index < 50
})
console.log(arr3)//[ 1, 12, 32, 2, 3, 3, 5 ]
Array.prototype.myFilter=function(fn){
// 判断调用myforEach的对象是不是一个数组
if(!Array.isArray(this)){
console.log('not a array')
}
// 判断传入的是不是函数
if (typeof fn != 'function') {
console.log(`${fn} is not a function`)
return false
}
// 对数组每一项执行该函数
let resArrary = []
for(let index = 0; index < this.length; index++){
let a = fn(this[index], index, this)
if(a){
resArrary.push(this[index])
}
}
return resArrary
}
var arr3 = arr.myFilter(function(item,index,arr) {
return item+index < 50
})
console.log(arr3)//[ 1, 12, 32, 2, 3, 3, 5 ]
reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素。
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
total最初初始值默认是数组第一个元素,当有initValue时为initValue
高级技巧请点击下方大佬文章
reduce()方法详解及高级技巧
var arr = [1, 12, 32, 2, 3, 120, 44, 3, 5];
var arr2 = [1, 2, 3, 4]
var arr3 = arr.reduce((total, item, index, arr)=>{
return item+total
},0)
console.log(arr3)//222
Array.prototype.myReduce=function(fn,initValue){
// 判断调用myforEach的对象是不是一个数组
if(!Array.isArray(this)){
console.log('not a array')
}
// 判断传入的是不是函数
if (typeof fn != 'function') {
console.log(`${fn} is not a function`)
return false
}
var value = this[0];
// 对数组每一项执行该函数
// 有传入第二个参数
if(arguments.length > 1){
for(let index = 0; index < this.length; index++){
initValue = fn.call(this, initValue, this[index], index, this)
}
}
else{
for(let index = 1; index < this.length; index++){
value = fn.call(this, value, this[index], index, this)
initValue = value;
}
}
return initValue
}
function test(total,item,index,arr) {
return total+item
}
var arr3 = arr.myReduce(test,0)
console.log(arr3)//222
// 小注意:
// var arr4 = []
// console.log(arr4.reduce(test,0)) //0
// console.log(arr4.reduce(test)) //TypeError: Reduce of empty array with no initial value
我们平时用到这些函数也需要注意一些小细节:
易错点
以下说不会改变原始数组是指:当数组中元素是值类型,绝对不会改变数组;如果是引用类型,则可以改变数组
- every、 some、find、findIndex、forEach、map、filter、reduce不会改变原始数组
- map、filter会返回新数组。map返回表达式执行的结果的数组项数组。filter是返回满足表达式的数组项数组
- foreach不能通过return返回指定的返回值。
- every、some 、filter 、map不会对空数组进行检测。
- find 、findIndex、reduce、forEach对于空数组是不会执行回调函数的。forEach、every、some、map、filter、reduce会跳过空元素。find、findIndex不跳过空元素。