徒手實現(xiàn)關于JavaScript的24+數(shù)組方法
這篇文章會和你一起探究24+原生數(shù)組方法的內(nèi)部實現(xiàn),相信你看完一定會有屬于自己不一樣的收獲。
一、遍歷類
1. forEach
基本使用:
forEach
一個日常用的非常多的遍歷函數(shù),你一定熟悉到不能再熟悉啦!這里我們著重看一些比較重要且容易忽略的點。mdn
- 該方法對數(shù)組的每個元素執(zhí)行一次給定的函數(shù),返回值是
undefiend
- 該方法按升序為數(shù)組中含有效值的每一項執(zhí)行一次
callback
函數(shù),未初始化的項將被跳過(例如在稀疏數(shù)組上)。 - 如果已經(jīng)存在的值被改變,則傳遞給
callback
的值是forEach()
遍歷到他們那一刻的值。 - 已刪除的項不會被遍歷到
舉個小例子:
let demoArr = [ 1, 2, 3, 4, , 5 ] demoArr.forEach((it, i) => { if (i === 1) { // 后添加進去的不會被訪問到 demoArr.push(5) } else if (i === 2) { // 4將不會被訪問到,而4-4會被訪問到 demoArr.splice(3, 1, '4-4') } console.log(it) }) /* 1 2 3 4-4 5 */
代碼實現(xiàn):
Array.prototype.forEach2 = function (callback, thisCtx) { if (typeof callback !== 'function') { throw `${callback} is not a function` } const length = this.length let i = 0 while (i < length) { // 被刪除的,新增的元素索引i不在數(shù)組內(nèi),所以不會被訪問到 if (i in this) { callback.call(thisCtx, this[ i ], i, this) } i++ } }
同樣用剛才的例子,改下后的輸出是一樣的
測試一把:
// 測試 let demoArr = [ 1, 2, 3, 4, , 5 ] demoArr.forEach2((it, i) => { if (i === 1) { // 后添加進去的不會被訪問到 demoArr.push(5) } else if (i === 2) { // 4將不會被訪問到,相仿4-4會被訪問到 demoArr.splice(3, 1, '4-4') } console.log(it) }) /* 1 2 3 4-4 5 */
2. map
基本使用:
map
方法創(chuàng)建一個新數(shù)組,其結果是該數(shù)組中的每個元素是調用一次提供的函數(shù)后的返回值。mdn
注意點:
callback
函數(shù)只會在有值的索引上被調用- 從來沒被賦過值或者使用 delete 刪除的索引則不會被調用。
// 注意索引為2的位置沒有賦值 let arr = [ 1, 2, ,4, 5 ] // 刪除索引3 delete arr[3] console.log(arr.map((it) => it * it)) // [ 1, 4, 25 ]
代碼實現(xiàn):
Array.prototype.map2 = function (callback, thisCtx) { if (typeof callback !== 'function') { throw `${callback} is not a function` } const length = this.length let i = 0 // map返回值是一個新的數(shù)組 let newArray = [] while (i < length) { // 被刪除的,未初始化的都不會被遍歷到 if (i in this) { newArray.push(callback.call(thisCtx, this[ i ], i, this)) } i++ } // 返回新的數(shù)組 return newArray }
測試一把:
let arr = [ 0, 1, 2, 3, 4,, 5 ] let arr2 = arr.map2(function (it, i, array) { console.log(it, i, array, this) return it * it }, { name: '前端胖頭魚' }) console.log(arr2)
3. every
基本使用:
every
方法測試一個數(shù)組內(nèi)的所有元素是否都能通過某個指定函數(shù)的測試。它返回一個布爾值。mdn
注意點:
- 若收到一個空數(shù)組,此方法在一切情況下都會返回 true。
- callback 只會為那些已經(jīng)被賦值的索引調用
- 不會為那些被刪除或從未被賦值的索引調用
// 舉例 let emptyArr = [] // 空數(shù)組直接返回true console.log(emptyArr.every((it) => it > 0)) // true // 有未被賦值的 let arr = [ 0, 1, 2, 3, 4,, 5, -1 ] // 刪除元素 delete arr[7] console.log(arr.every((it) => it >= 0)) // true
代碼實現(xiàn):
Array.prototype.every2 = function (callback, thisCtx) { if (typeof callback !== 'function') { throw `${callback} is not a function` } const length = this.length let i = 0 // 空函數(shù)不會走進循環(huán) while (i < length) { // 只要有一個值不符合callback預期就返回false if (i in this && !callback.call(thisCtx, this[ i ], i, this)) { return false } i++ } return true }
測試一把:
還是拿例子做測試
let emptyArr = [] console.log(emptyArr.every2((it) => it > 0)) // true let arr = [ 0, 1, 2, 3, 4,, 5, -1 ] delete arr[7] console.log(arr.every2((it) => it >= 0)) // true
4. some
基本使用:
some
方法測試數(shù)組中是不是至少有1個元素通過了被提供的函數(shù)測試。它返回的是一個Boolean
類型的值。 mdn
注意點:
callback
只會在那些”有值“的索引上被調用,不會在那些被刪除或從來未被賦值的索引上調用。
舉個例子
let emptyArr = [] // 空數(shù)組直接返回false console.log(emptyArr.some((it) => it > 0)) // false let arr = [ 0, 1, 2, 3, 4,, 5, -1 ] // 還沒有遍歷前把-1刪除了,唯一小于0的值不存在了,即返回false delete arr[7] console.log(arr.some((it) => it < 0)) // false
代碼實現(xiàn):
Array.prototype.some2 = function (callback, thisCtx) { if (typeof callback !== 'function') { throw `${callback} is not a function` } const length = this.length let i = 0 while (i < length) { // 只要有一個元素符合callback條件,就返回true if (i in this && callback.call(thisCtx, this[ i ], i, this)) { return true } i++ } return false }
測試一把:
let emptyArr = [] // 空數(shù)組直接返回true console.log(emptyArr.some2((it) => it > 0)) // false let arr = [ 0, 1, 2, 3, 4,, 5, -1 ] delete arr[7] console.log(arr.some2((it) => it < 0)) // false console.log(arr.some2((it) => it > 0)) // true
5. filter
基本使用:
filter
方法創(chuàng)建一個新數(shù)組, 其包含通過所提供函數(shù)測試的所有元素。 mdn
注意點:
filter
為數(shù)組中的每個元素調用一次callback
函數(shù),并利用所有使得callback
返回true
或等價于true
的值的元素創(chuàng)建一個新數(shù)組。callback
只會在已經(jīng)賦值的索引上被調用,對于那些已經(jīng)被刪除或者從未被賦值的索引不會被調用。- 那些沒有通過
callback
測試的元素會被跳過,不會被包含在新數(shù)組中。
// 索引為5的位置,沒有初始化值,不會被遍歷 let arr = [ 0, 1, 2, -3, 4,, 5 ] // 刪除掉最后一個元素 delete arr[6] // 過濾出大于0的值 let filterArr = arr.filter((it) => it > 0) console.log(filterArr) // [ 1, 2, 4 ]
代碼實現(xiàn):
Array.prototype.filter2 = function (callback, thisCtx) { if (typeof callback !== 'function') { throw `${callback} is not a function` } const length = this.length let newArray = [] let i = 0 while (i < length) { if (i in this && callback.call(thisCtx, this[ i ], i, this)) { newArray.push(this[ i ]) } i++ } return newArray }
測試:
// 索引為5的位置,沒有初始化值,不會被遍歷 let arr = [ 0, 1, 2, -3, 4,, 5 ] // 刪除掉最后一個元素 delete arr[6] // 過濾出大于0的值 let filterArr = arr.filter2((it) => it > 0) console.log(filterArr) // [ 1, 2, 4 ]
6. reduce
基本使用:
reduce
方法對數(shù)組中的每個元素執(zhí)行一個由您提供的reducer
函數(shù)(升序執(zhí)行),將其結果匯總為單個返回值 mdn
這個函數(shù)稍微復雜一些,我們用一個例子來看一下他是怎么用的。
const sum = [1, 2, 3, 4].reduce((prev, cur) => { return prev + cur; }) console.log(sum) // 10 // 初始設置 prev = initialValue = 1, cur = 2 // 第一次迭代 prev = (1 + 2) = 3, cur = 3 // 第二次迭代 prev = (3 + 3) = 6, cur = 4 // 第三次迭代 prev = (6 + 4) = 10, cur = undefined (退出)
代碼實現(xiàn):
Array.prototype.reduce2 = function (callback, initValue) { if (typeof callback !== 'function') { throw `${callback} is not a function` } let pre = initValue let i = 0 const length = this.length // 當沒有傳遞初始值時,取第一個作為初始值 if (typeof pre === 'undefined') { pre = this[0] i = 1 } while (i < length) { if (i in this) { pre = callback(pre, this[ i ], i, this) } i++ } return pre }
測試:
const sum = [1, 2, 3, 4].reduce2((prev, cur) => { return prev + cur; }) console.log(sum) // 10
7. reduceRight
基本使用:
reduceRight
方法對數(shù)組中的每個元素執(zhí)行一個由您提供的reducer
函數(shù)(降序執(zhí)行),將其結果匯總為單個返回值 mdn
和reduce
很類似,唯一不同的是reduceRight
從右往左遍歷
const sum = [1, 2, 3, 4].reduce((prev, cur) => { console.log(cur) return prev + cur; }) // 2 1 // 3 2 // 4 3 console.log(sum) // 10 const sum2 = [1, 2, 3, 4].reduceRight((prev, cur) => { console.log(cur) return prev + cur; }) // 3 2 // 2 1 // 1 0 console.log(sum2) // 10
代碼實現(xiàn):
Array.prototype.reduceRight2 = function (callback, initValue) { if (typeof callback !== 'function') { throw `${callback} is not a function` } let pre = initValue const length = this.length // 從最后一個元素開始遍歷 let i = length - 1 // 如果沒有傳遞初始值,則取最后一個作為初始值 if (typeof pre === 'undefined') { pre = this[i] i-- } while (i >= 0) { if (i in this) { pre = callback(pre, this[ i ], i, this) } i-- } return pre }
測試:
const sum = [1, 2, 3, 4].reduceRight2((prev, cur) => { console.log(cur) return prev + cur; }) // 3 2 // 2 1 // 1 0 console.log(sum) // 10
二、查找類
1. find
基本使用:
find 方法返回數(shù)組中滿足測試函數(shù)的第一個元素的值。否則返回
undefined
, mdn
注意點:
find
方法對數(shù)組中的每一項元素執(zhí)行一次callback
函數(shù),直至有一個callback
返回 true- 當找到了這樣一個元素后,該方法會立即返回這個元素的值,否則返回
undefined
callback
函數(shù)會為數(shù)組中的每個索引調用即從 0 到length - 1
,而不僅僅是那些被賦值的索引。(這個點是和前面幾個函數(shù)不一樣的地方)
let arr = [ 0, 1, 2, 3, 4,, 5 ] let index = arr.find((it) => { return it > 3 }, { name: '前端胖頭魚' }) console.log(index) // 4
代碼實現(xiàn):
Array.prototype.find2 = function (callback, thisCtx) { if (typeof callback !== 'function') { throw `${callback} is not a function` } const length = this.length let i = 0 while (i < length) { const value = this[ i ] // 只要有一個元素符合callback回調函數(shù)的邏輯,就返回元素value if (callback.call(thisCtx, value, i, this)) { return value } i++ } // 否則返回undefined return undefined }
測試:
let arr = [ 0, 1, 2, 3, 4,, 5 ] let index = arr.find2(function (it, i, array) { console.log(it, i, array, this) return it > 3 }, { name: '前端胖頭魚' }) console.log(index) // 4
2. findIndex
基本使用:
findIndex
方法返回數(shù)組中滿足提供的測試函數(shù)的第一個元素的索引。若沒有找到對應元素則返回-1。 mdn- 和find函數(shù)不同的地方在于,
findIndex
是返回索引而非值, 注意點也和find基本一樣 - findIndex方法對數(shù)組中的每個數(shù)組索引0 ~ length-1(包括)執(zhí)行一次callback函數(shù),直到找到一個
callback
函數(shù)返回true的值。 - 如果找到這樣的元素,findIndex會立即返回該元素的索引。如果回調從不返回真值,或者數(shù)組的
length
為0,則findIndex
返回-1 - 與某些其他數(shù)組方法(如
Array#some
)不同,在稀疏數(shù)組中,即使對于數(shù)組中不存在的條目的索引也會調用回調函數(shù)
let arr = [ 0, 1, 2, 3, 4,, 5 ] let index = arr.findIndex((it, i, array) => { return it > 2 }) console.log(index) // 3
代碼實現(xiàn):
Array.prototype.findIndex2 = function (callback, thisCtx) { if (typeof callback !== 'function') { throw `${callback} is not a function` } const length = this.length let i = 0 while (i < length) { // 符合callback邏輯的直接返回索引i if (callback.call(thisCtx, this[ i ], i, this)) { return i } i++ } // 否則返回-1 return -1 }
測試:
let arr = [ 0, 1, 2, 3, 4,, 5 ] let index = arr.findIndex2(function (it, i, array) { console.log(it, i, array, this) return it > 2 }, { name: '前端胖頭魚' }) console.log(index) // 3
3. indexOf
基本使用:
indexOf
方法返回在數(shù)組中可以找到一個給定元素的第一個索引,如果不存在,則返回-1。 mdn
arr.indexOf(searchElement[, fromIndex])
注意點:
- 如果開始查找的索引值大于或等于數(shù)組長度,意味著不會在數(shù)組里查找,返回-1
- 如果參數(shù)中提供的索引值是一個負值,則將其作為數(shù)組末尾的一個抵消,即-1表示從最后一個元素開始查找,-2表示從倒數(shù)第二個元素開始查找 ,以此類推
- 如果參數(shù)中提供的索引值是一個負值,并不改變其查找順序,查找順序仍然是從前向后查詢數(shù)組
- 如果抵消后的索引值仍小于0,則整個數(shù)組都將會被查詢。其默認值為0.
const array = [2, 5, 9] console.log(array.indexOf(2)) // 0 console.log(array.indexOf(7)) // -1 console.log(array.indexOf(9, 2)) // 2 console.log(array.indexOf(2, -1)) // -1 console.log(array.indexOf(2, -3)) // 0
代碼實現(xiàn):
有了上面的注意點和基本你使用,聰明的你肯定一眼就知道怎么寫啦
Array.prototype.indexOf2 = function (targetEle, fromIndex) { const length = this.length fromIndex = +fromIndex || 0 // 數(shù)組為空或者從大于等于數(shù)組長度的地方開始檢索,都直接是-1 if (length === 0 || fromIndex >= length) { return -1 } /* 1. 從fromIndex開始搜索元素 2. fromIndex大于0時候直接取即可 3. 小于0先用長度減去fromIndex的絕對值,如果還是小于0,就直接取0即可 */ let i = Math.max(fromIndex >= 0 ? fromIndex : length - Math.abs(fromIndex), 0) while (i < length) { // 在數(shù)組內(nèi)的元素并且和targetEle強等 if (i in this && targetEle === this[ i ]) { return i } i++ } return -1 }
測試:
const array = [2, 5, 9] console.log(array.indexOf2(2)) // 0 console.log(array.indexOf2(7)) // -1 console.log(array.indexOf2(9, 2)) // 2 console.log(array.indexOf2(2, -1)) // -1 console.log(array.indexOf2(2, -3)) // 0
4. lastIndexOf
基本使用:
lastIndexOf
方法返回指定元素在數(shù)組中的最后一個的索引,如果不存在則返回 -1。 mdn
arr.lastIndexOf(searchElement[, fromIndex])
注意點:
- 從
arr.length - 1
位置開始逆向查找。 - 如果
fromIndex
大于或等于數(shù)組的長度,則整個數(shù)組會被查找。 - 如果
fromIndex
為負值,將其視為從數(shù)組末尾向前的偏移。即使該值為負,數(shù)組仍然會被從后向前查找。 - 如果
fromIndex
值為負時,其絕對值大于數(shù)組長度,則方法返回 -1,即數(shù)組不會被查找。
let array = [2, 5, 9, 2] console.log(array.lastIndexOf(2)) // 3 console.log(array.lastIndexOf(7)) // -1 console.log(array.lastIndexOf(2, 3)) // 3 console.log(array.lastIndexOf(2, 2)) // 0 console.log(array.lastIndexOf(2, -2)) // 0 console.log(array.lastIndexOf(2, -1)) // 3
代碼實現(xiàn):
Array.prototype.lastIndexOf2 = function (targetEle, fromIndex) { const length = this.length fromIndex = typeof fromIndex === 'undefined' ? length - 1 : fromIndex // 數(shù)組為空,以及該值為負時且絕對值大于數(shù)組長度,則方法返回 -1,即數(shù)組不會被查找。 if (length === 0 || fromIndex < 0 && Math.abs(fromIndex) >= length) { return -1 } let i if (fromIndex >= 0) { // 如果`fromIndex`大于或等于數(shù)組的長度,則整個數(shù)組會被查找。 // 也就是當大于數(shù)組length - 1時,會取length - 1 i = Math.min(fromIndex, length - 1) } else { i = length - Math.abs(fromIndex) } while (i >= 0) { // 等于targetEle時返回索引 if (i in this && targetEle === this[ i ]) { return i } // 逆向遍歷 i-- } // 沒找到返回-1 return -1 }
測試:
let array = [2, 5, 9, 2] console.log(array.lastIndexOf2(2)) // 3 console.log(array.lastIndexOf2(7)) // -1 console.log(array.lastIndexOf2(2, 3)) // 3 console.log(array.lastIndexOf2(2, 2)) // 0 console.log(array.lastIndexOf2(2, -2)) // 0 console.log(array.lastIndexOf2(2, -1)) // 3
5. includes
基本使用:
includes
方法用來判斷一個數(shù)組是否包含一個指定的值,如果包含則返回 true,否則返回false
。mdn
arr.includes(valueToFind[, fromIndex])
注意點:
- 從fromIndex 索引處開始查找
valueToFind
。 - 如果為負值,則按升序從
array.length + fromIndex
的索引開始搜 - 數(shù)組中存在NaN的話
,[ ..., NaN ].includes(NaN
)為true
console.log([1, 2, 3].includes(2)) // true console.log([1, 2, 3].includes(4)) // false console.log([1, 2, 3].includes(3, 3)) // false console.log([1, 2, 3].includes(3, -1)) // true console.log([1, 2, NaN].includes(NaN)) // true
代碼實現(xiàn):
Array.prototype.includes2 = function (targetEle, fromIndex) { const length = this.length fromIndex = +fromIndex || 0 // 數(shù)組為空或者從大于等于數(shù)組長度的地方開始檢索,都直接是-1 if (length === 0 || fromIndex >= length) { return false } /* 1. 從fromIndex開始搜索元素 2. fromIndex大于0時候直接取即可 3. 小于0先用長度減去fromIndex的絕對值,如果還是小于0,就直接取0即可 */ let i = Math.max(fromIndex >= 0 ? fromIndex : length - Math.abs(fromIndex), 0) while (i < length) { const value = this[ i ] // 注意NaN情況 if (targetEle === value || typeof targetEle === 'number' && typeof value === 'number' && isNaN(targetEle) && isNaN(value)) { return true } i++ } return false }
測試:
console.log([1, 2, 3].includes2(2)) // true
console.log([1, 2, 3].includes2(4)) // false
console.log([1, 2, 3].includes2(3, 3)) // false
console.log([1, 2, 3].includes2(3, -1)) // true
console.log([1, 2, NaN].includes2(NaN)) // true
三、增刪改類
1. push
基本使用:
push
方法將一個或多個元素添加到數(shù)組的末尾,并返回該數(shù)組的新長度。mdn
const animals = ['pigs', 'goats', 'sheep'] animals.push('cows') console.log(animals, animals.length) // ["pigs", "goats", "sheep", "cows"], 4 animals.push('chickens', 'cats', 'dogs') console.log(animals, animals.length) // ["pigs", "goats", "sheep", "cows", "chickens", "cats", "dogs"], 7
代碼實現(xiàn):
Array.prototype.push2 = function (...pushEles) { const pushEleLength = pushEles.length const length = this.length let i = 0 while (i < pushEleLength) { this[ length + i ] = pushEles[ i ] i++ } return this.length }
測試:
const animals = ['pigs', 'goats', 'sheep'] animals.push2('cows') console.log(animals, animals.length) // ["pigs", "goats", "sheep", "cows"], 4 animals.push2('chickens', 'cats', 'dogs') console.log(animals, animals.length) // ["pigs", "goats", "sheep", "cows", "chickens", "cats", "dogs"], 7
2. pop
基本使用:
pop方法從數(shù)組中刪除最后一個元素,并返回該元素的值。此方法更改數(shù)組的長度。mdn
let arr = [ 1, 2 ] let arr2 = [] console.log(arr.pop(), arr) // 2 [1] console.log(arr2.pop(), arr2) // undefined []
代碼實現(xiàn)和使用一樣簡單,只要把數(shù)組的最后一個元素返回,并且讓數(shù)組長度減1即可
代碼實現(xiàn):
Array.prototype.pop2 = function () { const length = this.length // 空數(shù)組上pop,直接返回undefined if (length === 0) { return undefined } const delEle = this[ length - 1 ] this.length = length - 1 return delEle }
測試:
let arr = [ 1, 2 ] let arr2 = [] console.log(arr.pop2(), arr) // 2 [1] console.log(arr2.pop2(), arr2) // undefined []
3. unshift
基本使用:
unshift
方法將一個或多個元素添加到數(shù)組的開頭,并返回該數(shù)組的新長度(該方法修改原有數(shù)組 ) 。
注意點:
- 如果傳入多個參數(shù),它們會被以塊的形式插入到對象的開始位置,它們的順序和被作為參數(shù)傳入時的順序一致。
- 傳入多個參數(shù)調用一次 unshift ,和傳入一個參數(shù)調用多次 unshift (例如,循環(huán)調用),它們將得到不同的結果。
例如:
let arr = [4,5,6] // 一次性插入 arr.unshift(1,2,3) console.log(arr) // [1, 2, 3, 4, 5, 6] let arr2 = [4,5,6] // 插入多次 arr2.unshift(1) arr2.unshift(2) arr2.unshift(3) console.log(arr2); // [3, 2, 1, 4, 5, 6]
代碼實現(xiàn):
Array.prototype.unshift2 = function (...unshiftEles) { // 借助擴展符,將需要添加的元素以塊的形式插入到數(shù)組前面 let newArray = [ ...unshiftEles, ...this ] let length = newArray.length let i = 0 if (unshiftEles.length === 0) { return length } // 重新復制給數(shù)組 while (i < length) { this[ i ] = newArray[ i ] i++ } return this.length }
測試:
let arr = [4,5,6] // 一次性插入 arr.unshift2(1,2,3) console.log(arr) // [1, 2, 3, 4, 5, 6] let arr2 = [4,5,6] // 插入多次 arr2.unshift2(1) arr2.unshift2(2) arr2.unshift2(3) console.log(arr2); // [3, 2, 1, 4, 5, 6]
4. shift
基本使用:
shift 方法從數(shù)組中刪除第一個元素,并返回該元素的值。 mdn
let arr = [ 1, 2 ] console.log(arr.shift(), arr) // 1 [2] console.log(arr.shift(), arr) // 2 []
代碼實現(xiàn):
Array.prototype.shift2 = function () { const length = this.length const delValue = this[ 0 ] let i = 1 while (i < length) { // 從第一個元素開始,后面的元素都往前移動一位 this[ i - 1 ] = this[ i ] i++ } // 設置好數(shù)組的長度 this.length = length - 1 // 返回刪除的值 return delValue }
測試:
let arr = [ 1, 2 ] console.log(arr.shift2(), arr) // 1 [2] console.log(arr.shift2(), arr) // 2 []
5. reverse
基本使用:
reverse
方法將數(shù)組中元素的位置顛倒,并返回該數(shù)組。即數(shù)組的第一個元素會變成最后一個,數(shù)組的最后一個元素變成第一個。mdn
``` javascript const arr = [1, 2, 3] console.log(arr) // [1, 2, 3] arr.reverse() console.log(arr) // [3, 2, 1]
代碼實現(xiàn):
Array.prototype.reverse2 = function () { // 設置雙指針,往中間靠攏 let i = 0 let j = this.length - 1 while (i < j) { // 第一個和最后一個,第二個和倒數(shù)第二個進行位置調換 [ this[ i ], this[ j ] ] = [ this[ j ], this[ i ] ] i++ j-- } return this }
測試:
const arr = [1, 2, 3] console.log(arr) // [1, 2, 3] arr.reverse2() console.log(arr) // [3, 2, 1]
6. fill
基本使用:
fill
方法用一個固定值填充一個數(shù)組中從起始索引到終止索引內(nèi)的全部元素。不包括終止索引。mdn
const array1 = [1, 2, 3, 4]; console.log(array1.fill(0, 2, 4)) // [1, 2, 0, 0] console.log(array1.fill(5, 1)) // [1, 5, 5, 5] console.log(array1.fill(6)) // [6, 6, 6, 6]
代碼實現(xiàn):
Array.prototype.fill2 = function (value, start, end) { const length = this.length start = start >> 0 // end沒填的話,默認是length,否則取填寫的 end = typeof end === 'undefined' ? length : end >> 0 // start最小取0,最大取length start = start >= 0 ? Math.min(start, length) : Math.max(start + length, 0) // end最小取0,最大取length end = end >= 0 ? Math.min(end, length) : Math.max(end + length, 0) // 填充指定范圍的索引為value while (start < end) { this[ start ] = value start++ } // 返回被修改的數(shù)組 return this }
測試:
const array1 = [1, 2, 3, 4]; console.log(array1.fill2(0, 2, 4)) // [1, 2, 0, 0] console.log(array1.fill2(5, 1)) // [1, 5, 5, 5] console.log(array1.fill2(6)) // [6, 6, 6, 6] 連接、拼接
7. concat
基本使用:
concat
方法用于合并兩個或多個數(shù)組。此方法不會更改現(xiàn)有數(shù)組,而是返回一個新數(shù)組 mdn
let num1 = [[1]] let num2 = [2, [3]] let num3=[5,[6]] let nums = num1.concat(num2) // [[1], 2, [3]] let nums2 = num1.concat(4, num3) // [[1], 4, 5,[6]]
代碼實現(xiàn):
Array.prototype.concat2 = function (...concatEles) { const length = concatEles.length // 數(shù)組本身展開一層 let newArray = [ ...this ] let i = 0 while (i < length) { const value = concatEles[ i ] // 對數(shù)組元素展開一層 Array.isArray(value) ? newArray.push(...value) : newArray.push(value) i++ } return newArray }
測試:
let num1 = [[1]] let num2 = [2, [3]] let num3=[5,[6]] let nums = num1.concat2(num2) // [[1], 2, [3]] let nums2 = num1.concat2(4, num3) // [[1], 4, 5,[6]]
8. join
基本使用:
join
方法將一個數(shù)組的所有元素通過字符標識連接成一個字符串并返回這個字符串。如果數(shù)組只有一個項目,那么將返回該項目而不使用分隔符。
const elements = ['Fire', 'Air', 'Water'] const elements2 = ['Fire'] console.log(elements.join()) // Fire,Air,Water console.log(elements.join('')) // FireAirWater console.log(elements.join('-')) // Fire-Air-Water console.log(elements2.join('-')) // Fire
代碼實現(xiàn):
Array.prototype.join2 = function (format = ',') { const length = this.length // 保存最后一個元素,因為他不參與format連接 let lastEle = this[ length - 1 ] let string = '' if (length === 0) { return string } for (i = 0; i < length - 1; i++) { string += this[ i ] + format } return string + lastEle }
測試:
const elements = ['Fire', 'Air', 'Water'] const elements2 = ['Fire'] console.log(elements.join2()) // Fire,Air,Water console.log(elements.join2('')) // FireAirWater console.log(elements.join2('-')) // Fire-Air-Water console.log(elements2.join2('-')) // Fire
四、靜態(tài)方法
1. Array.isArray
基本使用:
Array.isArray()
用于確定傳遞的值是否是一個 Array。
Array.isArray([1, 2, 3]) // true Array.isArray({foo: 123}) // false Array.isArray("foobar") // false Array.isArray(undefined) // false
代碼實現(xiàn):
這個非常簡單,只需要一句話就可以
Array.isArray2 = function (ele) { return Object.prototype.toString.call(ele) === '[object Array]'; }
測試:
Array.isArray2([1, 2, 3]) // true Array.isArray2({foo: 123}) // false Array.isArray2("foobar") // false Array.isArray2(undefined) // false
2. Array.of
基本使用:
Array.of
方法創(chuàng)建一個具有可變數(shù)量參數(shù)的新數(shù)組實例,而不考慮參數(shù)的數(shù)量或類型。
注意點:
Array.of()
和 Array 構造函數(shù)之間的區(qū)別在于處理整數(shù)參數(shù):Array.of(7)
創(chuàng)建一個具有單個元素 7 的數(shù)組,而 Array(7) 創(chuàng)建一個長度為7的空數(shù)組(注意: 這是指一個有7個空位(empty)的數(shù)組,而不是由7個undefined組成的數(shù)組)
Array.of(7); // [7] Array.of(1, 2, 3); // [1, 2, 3] Array(7); // [ , , , , , , ] Array(1, 2, 3); // [1, 2, 3]
代碼實現(xiàn):
實現(xiàn)思路就是把你穿進去的值,挨個賦值到當前數(shù)組即可
Array.of2 = function (...eles) { const length = eles.length let i = 0 let newArray = [] while (i < length) { newArray[ i ] = eles[ i ] i++ } return newArray }
測試:
Array.of2(7); // [7] Array.of2(1, 2, 3); // [1, 2, 3]
五、扁平類
1. flat
基本使用:
flat()
方法會按照一個可指定的深度遞歸遍歷數(shù)組,并將所有元素與遍歷到的子數(shù)組中的元素合并為一個新數(shù)組返回。 mdn
const arr1 = [0, 1, 2, [3, 4]]; console.log(arr1.flat()) // [0, 1, 2, 3, 4] 默認會平鋪展開一層 const arr2 = [0, 1, 2, [[[3, 4]]]] console.log(arr2.flat(2)) // [0, 1, 2, [3, 4]] 指定展開兩層
代碼實現(xiàn):
Array.prototype.flat2 = function (depth = 1) { const result = [] const flat = (arr, depth) => { for (let item of arr) { // 當層數(shù)還未全部展開的時候,進行遞歸處理 if (Array.isArray(item) && depth > 0) { flat(item, depth - 1) } else { // 去除空元素,添加非undefined元素 item !== void 0 && result.push(item) } } } flat(this, depth) return result }
測試:
const arr1 = [0, 1, 2, [3, 4]]; console.log(arr1.flat2()) // [0, 1, 2, 3, 4] const arr2 = [0, 1, 2, [[[3, 4]]]] console.log(arr2.flat2(2)) // [0, 1, 2, [3, 4]]
2. flatMap
基本使用:
flatMap
方法首先使用映射函數(shù)映射每個元素,然后將結果壓縮成一個新數(shù)組。它與 map 連著深度值為1的 flat 幾乎相同。 mdn
let arr = [1, 2, 3, 4] arr.flatMap(x => [x * 2]) // [2, 4, 6, 8]
代碼實現(xiàn):
Array.prototype.flatMap2 = function (callback, thisCtx) { if (typeof callback !== 'function') { throw `${callback} is not a function` } // map和flat具體實現(xiàn)可以看map.js和flat.js return this.map(function (it, i, array) { return callback.call(thisCtx, it, i, array) }).flat(1) }
測試:
let arr = [1, 2, 3, 4] arr.flatMap2(x => [x * 2]) // [2, 4, 6, 8]
結尾:
到此這篇關于徒手實現(xiàn)關于JavaScript的24+數(shù)組方法的文章就介紹到這了,更多相關實現(xiàn)關于JavaScript的24+數(shù)組方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
國慶將至,祝大家節(jié)日快樂,浪浪浪七天樂。
相關文章
autojs長寬不定的圖片在正方形圖片居中實現(xiàn)詳解
這篇文章主要為大家介紹了autojs長寬不定的圖片在正方形圖片居中實現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-01-01微信小程序 ES6Promise.all批量上傳文件實現(xiàn)代碼
這篇文章主要介紹了微信小程序 ES6Promise.all批量上傳文件實現(xiàn)代碼的相關資料,需要的朋友可以參考下2017-04-04