迭代函數與迭代函數的實現


前言

說到迭代方法,最先想到的是什么?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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM