若是對技比較自信,請直接看實現的源碼javascript
若是想回顧一下基礎,請按文章順序閱讀前端
說到迭代方法,最早想到的是什麼?forEach
仍是map
,迭代的方法ES5提供了5種方法java
如下定義來自 JavaScript高級程序設計windows
每一個方法都接收兩個參數數組
傳入這些方法中的函數會接收3個參數框架
迭代函數執行後可能會也可能不會影響返回結果 (霧..)函數
ES5提供的迭代函數工具
true
,則返回true
true
,則返回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高程上說明 是運行該函數的做用域對象,能夠看一下經典的例子ui
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()
// 張三
// 張三
// 張三
複製代碼
對數組中的每一項運行給定函數,若是該函數每一項都返回
true
,則返回true
var array = [1,2,3,4,5,6,7,8,9]
var result = array.every(e => {})
console.log(result); //
> false
複製代碼
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
複製代碼
對數組中的每一項運行給定函數,若是該函數任意一項返回
true
,則返回true
var array = [1,2,3,4,5,6,7,8,9]
var result = array.some(e => {})
console.log(result); //
> false
複製代碼
var array = [1,2,3,4,5,6,7,8,9]
var result = array.some(e => {
return e > 8
})
console.log(result);
var array = [1,2,3,4,5,6,7,8,9]
var result = array.some(e => {
return e > 9
})
console.log(result);
> false
複製代碼
以上兩個都不是很經常使用,可是毫無疑問在特定的需求下,這個要比用forEach代碼要簡潔不少
對數組中的每一項運行給定函數,該函數會返回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
函數在平常當中比較經常使用
對數組中的每一項運行給定函數,返回每次函數調用的結果組成的數組
var array = [1,2,3,4,5,6,7,8,9]
var result = array.map(e => {
return e>5
})
console.log(result);
> [false, false, false, false, false, true, true, true, true]
var array = [1,2,3,4,5,6,7,8,9]
var result = array.map(e => {
return e*2
})
console.log(result);
> [2, 4, 6, 8, 10, 12, 14, 16, 18]
複製代碼
對數組中的每一項運行給定函數,無返回值
var array = [1,2,3,4,5,6,7,8,9]
var arraypush = []
var result = array.forEach(e => {
if (e > 5) {
arraypush.push(e)
}
})
console.log(arraypush);
> [6, 7, 8, 9]
複製代碼
最純粹的迭代函數,彷佛forEach是處理外部數組最好的選擇
到這裏,我想起了我第一次使用filter
函數的時候,我驚呆了,這函數太強大了!
如此好用的工具函數,不本身實現一遍怎麼能作到徹底瞭解
如下函數爲本身實現的,並非源碼,如有錯誤請指點!
首先明顯forEach是Array上的原型鏈上的函數因此第一件事就是建立一個原型方法
Array.prototype.MyforEach = function (){}
複製代碼
forEact 第一個參數爲一個匿名函數 第二個參數爲this指向 因此
Array.prototype.MyforEach = function (fn,obj){}
複製代碼
forEach會迭代調用它的數組因此內部確定是循環
Array.prototype.MyforEach = function (fn,obj){
let len = this.length
for (let index = 0; index < len; index++) {
fn(this[index],index,this)
}
}
複製代碼
可是咱們尚未考慮this指向的事情,因此還須要添加一些調整this的代碼
Array.prototype.MyforEach = function (fn,obj){
let len = this.length
if (obj != undefined) {
fn = fn.bind(obj)
}
for (let index = 0; index < len; index++) {
fn(this[index],index,this)
}
}
複製代碼
運行一下試試,就用以前的例子
var array = [1,2,3,4,5,6,7,8,9]
Array.prototype.MyforEach = function (fn,obj){
let len = this.length
if (obj != undefined) {
fn = fn.bind(obj)
}
for (let index = 0; index < len; index++) {
fn(this[index],index,this)
}
}
var obj2 = {
name: '張三',
times:[1,2,3],
print:function () {
this.times.MyforEach(function(res) {
console.log(this.name);
},this)
}
}
obj2.print()
> 張三
> 張三
> 張三
複製代碼
map與forEach的區別是
因此只要在迭代函數內部建立一個數組,每次迭代都push進去,最後返回出去就好啦
Array.prototype.Mymap = function (fn,obj){
var resultData = []
var len = this.length
if (obj != undefined) {
fn = fn.bind(obj)
}
for (let index = 0; index < len; index++) {
resultData.push(fn(this[index],index,this))
}
return resultData
}
複製代碼
運行一下
var array = [1,2,3,4,5,6,7,8,9,]
var result = array.Mymap(e => {
return e*2
})
console.log(result);
> [2, 4, 6, 8, 10, 12, 14, 16, 18]
複製代碼
some與every都會有一個特色 默認返回false
不一樣的地方在於
some要求 所有返回false
返回false
every要求 所有返回true
返回true
// -- every --
Array.prototype.Myevery = function (fn,obj) {
var len = this.length
if (obj != undefined) {
fn = fn.bind(obj)
}
for (let index = 0; index < len; index++) {
if (fn(this[index],index,this) == undefined) { // 無返回值 默認返回false
return false
}else if (fn(this[index],index,this) !== true) { // 出現一個不爲 true 就中止迭代 返回結果
return false
}
}
return true
}
// -- some --
Array.prototype.Mysome = function (fn,obj) {
var len = this.length
if (obj != undefined) {
fn = fn.bind(obj)
}
for (let index = 0; index < len; index++) {
if (fn(this[index],index,this) == undefined) {
return false
} else if (fn(this[index],index,this) !== false) {
return true
}
}
return false
}
複製代碼
相信到這裏,你也能夠直接實現一個fliter函數了,僅僅是多添加一個數組
Array.prototype.Myfilter = function (fn, obj) {
let resultData = []
var len = this.length
if (obj != undefined) {
fn = fn.bind(obj)
}
for (let index = 0; index < len; index++) {
if (fn(this[index],index,this)) { // 返回true則進行處理
resultData.push(this[index]) // 注意不是push函數結果
}
}
return resultData
}
// -- 運行 --
var array = [1,2,3,4,5,6,7,8,9]
var result = array.Myfilter(e => {
return e>5
})
console.log(result);
> [6, 7, 8, 9]
複製代碼
perfect! 😉
原來不少東西,並無想象的那麼複雜
想起了以前掘金上的 中止學習框架
一文,以及後面各位大佬的 駁 ....中止學習框架
,說到底都是爲了告訴咱們,無論學習什麼,都要打好基礎,做爲前端開發者,最最基礎的就是打好JavaScript
的基礎,基礎紮實,學習框架都不是困難事情