迭代函数与迭代函数的实现

前言

说到迭代方法,最先想到的是什么?forEach还是map,迭代的方法ES5提供了5种方法。

每个方法都接收两个参数:

  1.在每一项上运行的函数

  2.运行该函数的作用域对象(影响this的值)

传入这些方法中的函数会接收3个参数:

  1.数组项的值

  2.该项在数组的位置

  3.数组对象本身

迭代函数执行后可能会也可能不会影响返回结果 (雾..)

ES5提供的迭代函数:

  • forEach(): 对数组中的每一项运行给定函数,无返回值
  • every(): 对数组中的每一项运行给定函数,如果该函数每一项都返回true,则返回true
  • some(): 对数组中的每一项运行给定函数,如果该函数任意一项返回true,则返回true
  • map(): 对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组
  • filter(): 对数组中的每一项运行给定函数,该函数会返回true的项组成的数组

参数说明

let array = [1,2,3,4,5,6,7,8,9]
array.forEach((element,index,array) => {
  console.log(`当前遍历元素${element}`);
  console.log(`当前元素位置${index}`);
  console.log(`数组本身${array}`);
})

> 当前遍历元素1
> 当前元素位置0
> 数组本身1,2,3,4,5,6,7,8,9
> 当前遍历元素2
> 当前元素位置1
> 数组本身1,2,3,4,5,6,7,8,9
> 当前遍历元素3
> 当前元素位置2
> 数组本身1,2,3,4,5,6,7,8,9

forEach可以说是最常用的一个迭代方法了,该方法没有返回值,与for循环的效果一样。

forEach的第二个参数,js高程上说明 是运行该函数的作用域对象,可以看一下经典的例子:

let obj2 = {
  name: '张三',
  times:[1,2,3],
  print:function () {
    this.times.forEach(function(res) {
      console.log(this.name);
    },this)
  }
}
// 迭代函数内部的function默认指向windows 第二个参数调整了this指向
obj2.print()
// 张三
// 张三
// 张三

如果这么写看不太懂的话,看箭头函数的写法一下子就能明白。

let obj2 = {
  name: '张三',
  times:[1,2,3],
  print:function () {
    this.times.forEach(res => {
      console.log(name);
    })
  }
}
// 箭头函数this指向父级,所以他不需要调整this
obj2.print()
// 张三
// 张三
// 张三

every(判断函数)

对数组中的每一项运行给定函数,如果该函数每一项都返回true,则返回true。

默认返回false

var array = [1,2,3,4,5,6,7,8,9]
var result = array.every(e => {})
console.log(result); // 
> false 

全部ture才会返回true

var array = [1,2,3,4,5,6,7,8,9]
var result = array.every(e => {
  return e > 0
})
console.log(result);
> true
 
var array = [1,2,3,4,5,6,7,8,9]
var result = array.every(e => {
  return e > 1
})
console.log(result);
> false

some(判断函数)

对数组中的每一项运行给定函数,如果该函数任意一项返回true,则返回true。

默认返回false

var array = [1,2,3,4,5,6,7,8,9]
var result = array.some(e => {})
console.log(result); // 
> false 

全部false才会返回false

var array = [1,2,3,4,5,6,7,8,9]
var result = array.some(e => {
  return e > 8
})
console.log(result);
> true
 
var array = [1,2,3,4,5,6,7,8,9]
var result = array.some(e => {
  return e > 9
})
console.log(result);
> false

以上两个都不是很常用,但是毫无疑问在特定的需求下,这个要比用forEach代码要简洁很多。

filter(过滤函数)

对数组中的每一项运行给定函数,该函数会返回true的项组成的数组。

var array = [1,2,3,4,5,6,7,8,9]
var result = array.filter(e => {
  return e>5
})
console.log(result);
> [6, 7, 8, 9]

上面的例子,array数组里面大于5的数会被过滤出来,filter函数在日常当中比较常用。

  1 //map(处理函数)
  2 //对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组
  3 var array = [1,2,3,4,5,6,7,8,9]
  4 var result = array.map(e => {
  5   return e>5
  6 })
  7 console.log(result);
  8 //> [false, false, false, false, false, true, true, true, true]
  9  
 10 var array = [1,2,3,4,5,6,7,8,9]
 11 var result = array.map(e => {
 12   return e*2
 13 })
 14 console.log(result);
 15 //> [2, 4, 6, 8, 10, 12, 14, 16, 18]
 16  
 17 //forEach(迭代函数)对数组中的每一项运行给定函数,无返回值。
 18 var array = [1,2,3,4,5,6,7,8,9]
 19 var arraypush = []
 20 var result = array.forEach(e => {
 21   if (e > 5) {
 22     arraypush.push(e)
 23   }
 24 })
 25 console.log(arraypush);
 26 //> [6, 7, 8, 9]
 27 //最纯粹的迭代函数,似乎forEach是处理外部数组最好的选择。
 28 //到这里,我想起了我第一次使用filter函数的时候,我惊呆了,这函数太强大了!
 29 //如此好用的工具函数,不自己实现一遍怎么能做到完全了解。
 30 //以下函数为自己实现的,并不是源码,若有错误请指点!
 31  
 32 //实现forEach首先明显forEach是Array上的原型链上的函数所以第一件事就是创建一个原型方法:
 33 //Array.prototype.MyforEach = function (){}
 34 //forEact 第一个参数为一个匿名函数 第二个参数为this指向 所以:
 35 //Array.prototype.MyforEach = function (fn,obj){}
 36 //forEach会迭代调用它的数组所以内部肯定是循环:
 37 Array.prototype.MyforEach = function (fn,obj){
 38   let len = this.length
 39   for (let index = 0; index < len; index++) {
 40     fn(this[index],index,this)
 41   }
 42 }
 43 //但是我们还没有考虑this指向的事情,所以还需要添加一些调整this的代码:
 44 Array.prototype.MyforEach = function (fn,obj){
 45   let len = this.length
 46   if (obj !== 'undefined') {
 47     fn = fn.bind(obj)
 48   }
 49   for (let index = 0; index < len; index++) {
 50     fn(this[index],index,this)
 51   }
 52 }
 53 //运行一下试试,就用之前的例子:
 54 var array = [1,2,3,4,5,6,7,8,9]
 55 Array.prototype.MyforEach = function (fn,obj){
 56   let len = this.length
 57   if (obj !== 'undefined') {
 58     fn = fn.bind(obj)
 59   }
 60   for (let index = 0; index < len; index++) {
 61     fn(this[index],index,this)
 62   }
 63 }
 64  
 65 var obj2 = {
 66   name: '张三',
 67   times:[1,2,3],
 68   print:function () {
 69     this.times.MyforEach(function(res) {
 70       console.log(this.name);
 71     },this)
 72   }
 73 }
 74 obj2.print()
 75 //> 张三
 76 //> 张三
 77 //> 张三
 78  
 79 //实现mapmap与forEach的区别是:
 80 //1.map中如果是运算,会返回每次函数调用的新的结果组成的数组
 81 //2.map中如果是判断,会返回每次迭代结果组成的数组
 82 //所以只要在迭代函数内部创建一个数组,每次迭代都push进去,最后返回出去就好啦。
 83 Array.prototype.Mymap = function (fn,obj){
 84   var resultData = []
 85   var len = this.length
 86   if (obj !== 'undefined') {
 87     fn = fn.bind(obj)
 88   }
 89   for (let index = 0; index < len; index++) {
 90     resultData.push(fn(this[index],index,this))
 91   }
 92   return resultData
 93 }
 94 //运行一下:
 95 var array = [1,2,3,4,5,6,7,8,9,]
 96 var result = array.Mymap(e => {
 97     return e*2
 98 })
 99 console.log(result);
100 //> [2, 4, 6, 8, 10, 12, 14, 16, 18]
101  
102  
103 //实现 some everysome与every都会有一个特点 默认返回false。
104 //不同的地方在于:
105 //1.some要求 全部返回false返回false
106 //2.every要求 全部返回true返回true
107 // -- every -- 
108 Array.prototype.Myevery = function (fn,obj) {
109   var len = this.length
110   if (obj !== 'undefined') {
111     fn = fn.bind(obj)
112   }
113   for (let index = 0; index < len; index++) {
114     if (fn(this[index],index,this) == undefined) { // 无返回值 默认返回false
115       return false
116     }else if (fn(this[index],index,this) !== true) { // 出现一个不为 true 就停止迭代 返回结果
117       return false
118     }
119   }
120   return true
121 }
122  
123 // -- some -- 
124 Array.prototype.Mysome = function (fn,obj) {
125   var len = this.length
126   if (obj !== 'undefined') {
127     fn = fn.bind(obj)
128   }
129   for (let index = 0; index < len; index++) {
130     if (fn(this[index],index,this) == undefined) {
131       return false
132     } else if (fn(this[index],index,this) !== false) {
133       return true
134     }
135   }
136   return false
137 }
138  
139  
140 //实现fliter相信到这里,你也可以直接实现一个fliter函数了,仅仅是多添加一个数组。
141 Array.prototype.Myfilter = function (fn, obj) {
142   let resultData = []
143   var len = this.length
144   if (obj !== 'undefined') {
145     fn = fn.bind(obj)
146   }
147   for (let index = 0; index < len; index++) {
148     if (fn(this[index],index,this) === true) {
149       resultData.push(this[index]) // 注意不是push函数结果
150     }
151   }
152   return resultData
153 }
154  
155 // -- 运行 -- 
156  
157 var array = [1,2,3,4,5,6,7,8,9]
158 var result = array.Myfilter(e => {
159   return e>5
160 })
161 console.log(result);
162 //>  [6, 7, 8, 9]
163 //perfect! :stuck_out_tongue_closed_eyes:
164 //原来很多东西,并没有想象的那么复杂。

* 原文地址:https://juejin.im/post/5c331657e51d4551e325d6b4

原文地址:https://www.cnblogs.com/fei-H/p/11358483.html