你知道這20個數(shù)組方法是怎么實現(xiàn)的嗎?

英文 | https://javascript.plainenglish.io/20-javascript-array-methods-every-developer-should-know-6c04cc7a557d
翻譯 | 楊小愛
Array.prototype.forEach2 = function (callback, thisCtx) {if (typeof callback !== 'function') {throw `${callback} is not a function`}const length = this.lengthlet i = 0while (i < length) {// Deleted, the newly added element index i is not in the array, so it will not be accessedif (this.hasOwnProperty(i)) {callback.call(thisCtx, this[ i ], i, this)}i++}}
let demoArr = [ 1, 2, 3, 4, , 5 ]demoArr.forEach2((it, i) => {if (i === 1) {// 5 will not be printed outdemoArr.push(5)} else if (i === 2) {// 4 will not be printed out, but "4-4" will be printed outdemoArr.splice(3, 1, '4-4')}console.log(it)})/*1234-45*/
Array.prototype.map2 = function (callback, thisCtx) {if (typeof callback !== 'function') {throw `${callback} is not a function`}const length = this.lengthlet i = 0// The return value of the map method is a new arraylet newArray = []while (i < length) {// Deleted and uninitialized values will not be accessedif (this.hasOwnProperty(i)) {newArray.push(callback.call(thisCtx, this[ i ], i, this))}i++}// Return new arrayreturn 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: 'fatfish' })console.log(arr2) // [0, 1, 4, 9, 16, 25]
在空數(shù)組上調(diào)用 every 方法將返回 true。 回調(diào)方法只會被已經(jīng)賦值的索引調(diào)用。 如果值被刪除,回調(diào)將不會被調(diào)用
let emptyArr = []// Calling every method on an empty array returns trueconsole.log(emptyArr.every((it) => it > 0)) // true// The `callback` method will only be called by an index that has already been assigned a value.let arr = [ 0, 1, 2, 3, 4,, 5, -1 ]// The `callback` method will not be called when an array value is deleted or an index that has never been assigned a value.delete arr[7]console.log(arr.every((it) => it >= 0)) // true
代碼
Array.prototype.every2 = function (callback, thisCtx) {if (typeof callback !== 'function') {throw `${callback} is not a function`}const length = this.lengthlet i = 0// If the length of the array is 0, the while loop will not be enteredwhile (i < length) {// False will be returned as long as a value does not conform to the judgment of callbackif (this.hasOwnProperty(i) && !callback.call(thisCtx, this[ i ], i, this)) {return false}i++}return true}
let emptyArr = []// Calling every method on an empty array returns trueconsole.log(emptyArr.every2((it) => it > 0)) // true// The `callback` method will only be called by an index that has already been assigned a value.let arr = [ 0, 1, 2, 3, 4,, 5, -1 ]// The `callback` method will not be called when an array value is deleted or an index that has never been assigned a value.delete arr[7]console.log(arr.every2((it) => it >= 0)) // true
4、some
some() 方法測試數(shù)組中的至少一個元素是否通過了提供的函數(shù)實現(xiàn)的測試。
代碼
Array.prototype.some2 = function (callback, thisCtx) {if (typeof callback !== 'function') {throw `${callback} is not a function`}const length = this.lengthlet i = 0while (i < length) {// Returns true if any element meets the callback conditionif (this.hasOwnProperty(i) && callback.call(thisCtx, this[ i ], i, this)) {return true}i++}return false}
let emptyArr = []// An empty array will return falseconsole.log(emptyArr.some2((it) => it > 0)) // falselet arr = [ 0, 1, 2, 3, 4,, 5, -1 ]delete arr[7]console.log(arr.some2((it) => it < 0)) // falseconsole.log(arr.some2((it) => it > 0)) // true
5、filter
filter() 方法創(chuàng)建一個新數(shù)組,其中包含所有通過所提供函數(shù)實現(xiàn)的測試的元素。
Array.prototype.filter2 = function (callback, thisCtx) {if (typeof callback !== 'function') {throw `${callback} is not a function`}const length = this.length// The return value will be a new arraylet newArray = []let i = 0while (i < length) {if (this.hasOwnProperty(i) && callback.call(thisCtx, this[ i ], i, this)) {newArray.push(this[ i ])}i++}return newArray}
// The position with index 5 will not be traversed because it has no initialization valuelet arr = [ 0, 1, 2, -3, 4,, 5 ]// we try to remove the last elementdelete arr[6]// filter out values greater than 0let filterArr = arr.filter2((it) => it > 0)console.log(filterArr) // [ 1, 2, 4 ]
6、reduce
這個函數(shù)稍微復(fù)雜一些。讓我們用一個例子來看看它是如何使用的。
const sum = [1, 2, 3, 4].reduce((prev, cur) => {return prev + cur;})console.log(sum) // 10// initializationprev = initialValue = 1, cur = 2// step 1prev = (1 + 2) = 3, cur = 3// step 2prev = (3 + 3) = 6, cur = 4// step 3prev = (6 + 4) = 10, cur = undefined (quit)
代碼
Array.prototype.reduce2 = function (callback, initValue) {if (typeof callback !== 'function') {throw `${callback} is not a function`}let pre = initValuelet i = 0const length = this.length// When the initial value is not passed, use the first value of the array as the initial valueif (typeof pre === 'undefined') {pre = this[0]i = 1}while (i < length) {if (this.hasOwnProperty(i)) {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
const sum = [1, 2, 3, 4].reduce((prev, cur) => {console.log(prev, cur)return prev + cur;})// 1 2// 3 3// 6 4console.log(sum) // 10const sum2 = [1, 2, 3, 4].reduceRight((prev, cur) => {console.log(cur)return prev + cur;})// 4 3// 7 2// 9 1console.log(sum2) // 10
代碼
Array.prototype.reduceRight2 = function (callback, initValue) {if (typeof callback !== 'function') {throw `${callback} is not a function`}let pre = initValueconst length = this.length// Start with the last elementlet i = length - 1// If no initial value is passed, the last element is taken as the initial valueif (typeof pre === 'undefined') {pre = this[i]i--}while (i >= 0) {if (this.hasOwnProperty(i)) {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;})// 4 3// 7 2// 9 1console.log(sum) // 10
8、find
find() 方法返回提供的數(shù)組中滿足提供的測試功能的第一個元素。如果沒有值滿足測試函數(shù),則返回 undefined。
代碼
Array.prototype.find2 = function (callback, thisCtx) {if (typeof callback !== 'function') {throw `${callback} is not a function`}const length = this.lengthlet i = 0while (i < length) {const value = this[ i ]// As long as there is an element that matches the logic of the callback function, the element value is returnedif (callback.call(thisCtx, value, i, this)) {return value}i++}// otherwise return undefinedreturn undefined}
let arr = [ 0, 1, 2, 3, 4,, 5 ]let ele = arr.find2(function (it, i, array) {console.log(it, i, array, this)return it > 3}, { name: 'fatfish' })console.log(ele) // 4
9、findIndex
findIndex() 方法返回數(shù)組中滿足提供的測試函數(shù)的第一個元素的索引。否則,它返回 -1,表示沒有元素通過測試。
let arr = [ 0, 1, 2, 3, 4,, 5 ]let index = arr.findIndex((it, i, array) => {return it > 2})console.log(index) // 3
Array.prototype.findIndex2 = function (callback, thisCtx) {if (typeof callback !== 'function') {throw `${callback} is not a function`}const length = this.lengthlet i = 0while (i < length) {// Return index i that conforms to callback logicif (callback.call(thisCtx, this[ i ], i, this)) {return i}i++}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: 'fatfish' })console.log(index) // 3
const array = [2, 5, 9]console.log(array.indexOf(2)) // 0console.log(array.indexOf(7)) // -1console.log(array.indexOf(9, 2)) // 2console.log(array.indexOf(2, -1)) // -1console.log(array.indexOf(2, -3)) // 0console.log(array.indexOf(2, -4)) // 0
代碼
Array.prototype.indexOf2 = function (targetEle, fromIndex) {const length = this.lengthfromIndex = +fromIndex || 0// If the array is empty or the search starts from a place greater than or equal to the length of the array, it will directly return -1if (length === 0 || fromIndex >= length) {return -1}/*1. Search elements from fromIndex2. Use it directly when fromindex is greater than 03. If it is less than 0, first subtract the absolute value of fromIndex from the length. If it is still less than 0, take 0 directly*/let i = Math.max(fromIndex >= 0 ? fromIndex : length - Math.abs(fromIndex), 0)while (i < length) {// element in the array and equal to targetEleif (this.hasOwnProperty(i) && targetEle === this[ i ]) {return i}i++}return -1}
測試一下
const array = [2, 5, 9]console.log(array.indexOf2(2)) // 0console.log(array.indexOf2(7)) // -1console.log(array.indexOf2(9, 2)) // 2console.log(array.indexOf2(2, -1)) // -1console.log(array.indexOf2(2, -3)) // 0console.log(array.indexOf2(2, -4)) // 0
let array = [2, 5, 9, 2]console.log(array.lastIndexOf(2)) // 3console.log(array.lastIndexOf(7)) // -1console.log(array.lastIndexOf(2, 3)) // 3console.log(array.lastIndexOf(2, 2)) // 0console.log(array.lastIndexOf(2, -2)) // 0console.log(array.lastIndexOf(2, -1)) // 3
Array.prototype.lastIndexOf2 = function (targetEle, fromIndex) {const length = this.lengthfromIndex = typeof fromIndex === 'undefined' ? length - 1 : fromIndex// // Empty array, when fromIndex is negative and the absolute value is greater than the length of the array, the method returns -1, that is, the array will not be searched.if (length === 0 || fromIndex < 0 && Math.abs(fromIndex) >= length) {return -1}let iif (fromIndex >= 0) {// If `fromIndex` is greater than or equal to the length of the array, the entire array is searched.i = Math.min(fromIndex, length - 1)} else {i = length - Math.abs(fromIndex)}while (i >= 0) {// Returns the index when it is equal to targetEleif (i in this && targetEle === this[ i ]) {return i}i--}// Returns -1 when the current value is not foundreturn -1}
let array = [2, 5, 9, 2]console.log(array.lastIndexOf2(2)) // 3console.log(array.lastIndexOf2(7)) // -1console.log(array.lastIndexOf2(2, 3)) // 3console.log(array.lastIndexOf2(2, 2)) // 0console.log(array.lastIndexOf2(2, -2)) // 0console.log(array.lastIndexOf2(2, -1)) // 3
12、includes
includes() 方法確定數(shù)組是否在其條目中包含某個值,根據(jù)需要返回 true 或 false。
arr.includes(valueToFind[, fromIndex])console.log([1, 2, 3].includes(2)) // trueconsole.log([1, 2, 3].includes(4)) // falseconsole.log([1, 2, 3].includes(3, 3)) // falseconsole.log([1, 2, 3].includes(3, -1)) // trueconsole.log([1, 2, NaN].includes(NaN)) // true
代碼
Array.prototype.includes2 = function (targetEle, fromIndex) {const length = this.lengthfromIndex = +fromIndex || 0if (length === 0 || fromIndex >= length) {return false}// Search for elements from the position of fromIndexlet i = Math.max(fromIndex >= 0 ? fromIndex : length - Math.abs(fromIndex), 0)while (i < length) {const value = this[ i ]// Please note NaNif (targetEle === value || typeof targetEle === 'number' && typeof value === 'number' && isNaN(targetEle) && isNaN(value)) {return true}i++}return false}
console.log([1, 2, 3].includes2(2)) // trueconsole.log([1, 2, 3].includes2(4)) // falseconsole.log([1, 2, 3].includes2(3, 3)) // falseconsole.log([1, 2, 3].includes2(3, -1)) // trueconsole.log([1, 2, NaN].includes2(NaN)) // true
const animals = ['pigs', 'goats', 'sheep']animals.push('cows')console.log(animals, animals.length)// ["pigs", "goats", "sheep", "cows"], 4animals.push('chickens', 'cats', 'dogs')console.log(animals, animals.length)// ["pigs", "goats", "sheep", "cows", "chickens", "cats", "dogs"], 7
Array.prototype.push2 = function (...pushEles) {const pushEleLength = pushEles.lengthconst length = this.lengthlet i = 0while (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"], 4animals.push2('chickens', 'cats', 'dogs')console.log(animals, animals.length)// ["pigs", "goats", "sheep", "cows", "chickens", "cats", "dogs"], 7
let arr = [ 1, 2 ]let arr2 = []console.log(arr.pop(), arr) // 2 [1]console.log(arr2.pop(), arr2) // undefined []
Array.prototype.pop2 = function () {const length = this.length// If it is an empty array, return undefinedif (length === 0) {return undefined}const delEle = this[ length - 1 ]this.length = length - 1return delEle}
let arr = [ 1, 2 ]let arr2 = []console.log(arr.pop2(), arr) // 2 [1]console.log(arr2.pop2(), arr2) // undefined []
let arr = [4,5,6]// Insert multiple elements at oncearr.unshift(1,2,3)console.log(arr) // [1, 2, 3, 4, 5, 6]let arr2 = [4,5,6]// Insert multiple timesarr2.unshift(1)arr2.unshift(2)arr2.unshift(3)console.log(arr2); // [3, 2, 1, 4, 5, 6]
Array.prototype.unshift2 = function (...unshiftEles) {// With "...", Insert the element to be added in front of the arraylet newArray = [ ...unshiftEles, ...this ]let length = newArray.lengthlet i = 0if (unshiftEles.length === 0) {return length}// Recopy to arraywhile (i < length) {this[ i ] = newArray[ i ]i++}return this.length}
let arr = [4,5,6]// Insert multiple elements at oncearr.unshift2(1,2,3)console.log(arr) // [1, 2, 3, 4, 5, 6]let arr2 = [4,5,6]// Insert multiple timesarr2.unshift2(1)arr2.unshift2(2)arr2.unshift2(3)console.log(arr2); // [3, 2, 1, 4, 5, 6]
let arr = [ 1, 2 ]console.log(arr.shift(), arr) // 1 [2]console.log(arr.shift(), arr) // 2 []
代碼
Array.prototype.shift2 = function () {const length = this.lengthconst delValue = this[ 0 ]let i = 1while (i < length) {// Starting from the first element, the following elements move forward one bitthis[ i - 1 ] = this[ i ]i++}// Set the length of the arraythis.length = length - 1// Return deleted valuereturn delValue}
let arr = [ 1, 2 ]console.log(arr.shift2(), arr) // 1 [2]console.log(arr.shift2(), arr) // 2 []
17、reverse
(來自 MDN) reverse() 方法將數(shù)組反轉(zhuǎn)到位。第一個數(shù)組元素成為最后一個,最后一個數(shù)組元素成為第一個。
const arr = [1, 2, 3]console.log(arr) // [1, 2, 3]arr.reverse()console.log(arr) // [3, 2, 1]
Array.prototype.reverse2 = function () {let i = 0let j = this.length - 1while (i < j) {[ 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]
18、fill
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]
Array.prototype.fill2 = function (value, start, end) {const length = this.lengthstart = start >> 0// The default value of end is lengthend = typeof end === 'undefined' ? length : end >> 0// The minimum value of start is 0 and the maximum value is lengthstart = start >= 0 ? Math.min(start, length) : Math.max(start + length, 0)// The minimum value of end is 0 and the maximum value is lengthend = end >= 0 ? Math.min(end, length) : Math.max(end + length, 0)// The element that fills the specified range is valuewhile (start < end) {this[ start ] = valuestart++}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]
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]]
代碼
Array.prototype.concat2 = function (...concatEles) {const length = concatEles.length// The array itself needs to be expanded one layerlet newArray = [ ...this ]let i = 0while (i < length) {const value = concatEles[ i ]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]]
const elements = ['Fire', 'Air', 'Water']const elements2 = ['Fire']console.log(elements.join()) // Fire,Air,Waterconsole.log(elements.join('')) // FireAirWaterconsole.log(elements.join('-')) // Fire-Air-Waterconsole.log(elements2.join('-')) // Fire
代碼
Array.prototype.join2 = function (format = ',') {const length = this.length// Save the last element because it does not participate in the connection of formatlet 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,Waterconsole.log(elements.join2('')) // FireAirWaterconsole.log(elements.join2('-')) // Fire-Air-Waterconsole.log(elements2.join2('-')) // Fire
學(xué)習(xí)更多技能
請點擊下方公眾號
![]()

評論
圖片
表情
