44
头图

Preface

" public account. Maybe you have never met before, but it is very likely that you are too late to meet.

array is the most frequently used data structure in our daily work. It can help us solve many problems. It also contains nearly 33 methods. A brain map is classified as follows. You who are proficient in using arrays , Do you want to know their internal implementation principles?

This article will explore the internal implementation of the 24+ native array methods with you. I believe you will have a different harvest after reading it.

数组方法.png

Traversal class

1. forEach

Basic use

forEach are so many traversal functions that are used daily, you must be familiar enough that you can no longer be familiar with it! Here we focus on some of the more important and easily overlooked points. mdn
  1. This method executes the given function once for each element of the array, and the return value is undefiend .
  2. callback function once for each item in the with a valid value of in ascending order, and uninitialized items will be skipped (for example, on a sparse array).
  3. If the existing value is changed, the value passed to callback the value at forEach() traverses to them.
  4. Deleted items will not be traversed to

give a small example



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
*/

Code

Click to view the source code to achieve

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不在数组内,所以不会被访问到
    if (i in this) {
      callback.call(thisCtx, this[ i ], i, this)
    }

    i++
  }
}

Using the example just now, the output after the change is the same

Test a handful


// 测试
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

Basic use

map method creates a new array, and the result is that each element in the array is the return value after calling the provided function once. mdn

Note

  1. callback function will only be called on indexes that have a value
  2. Indexes that have never been assigned or delete will not be called.
// 注意索引为2的位置没有赋值
let arr = [ 1, 2, ,4, 5 ]

// 删除索引3
delete arr[3]

console.log(arr.map((it) => it * it))
// [ 1, 4, 25 ]

Code

Click to view the source code to achieve

Array.prototype.map2 = function (callback, thisCtx) {
  if (typeof callback !== 'function') {
    throw `${callback} is not a function`
  }

  const length = this.length
  let i = 0
  // map返回值是一个新的数组
  let newArray = []

  while (i < length) {
    // 被删除的,未初始化的都不会被遍历到
    if (i in this) {
      newArray.push(callback.call(thisCtx, this[ i ], i, this))
    }

    i++
  }
  // 返回新的数组
  return newArray
}

Test a handful

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)

image.png

3. every

Basic use

every method tests whether all elements in an array can pass the test of a specified function. It returns a boolean value. mdn

note

  1. If an empty array is received, this method will return true in all cases.
  2. callback will only be called for those indexes that have already been assigned
  3. Will not be called for indexes that have been deleted or have never been assigned
// 举例
let emptyArr = []
// 空数组直接返回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

Code

Click to view the source code to achieve


Array.prototype.every2 = function (callback, thisCtx) {
  if (typeof callback !== 'function') {
    throw `${callback} is not a function`
  }

  const length = this.length
  let i = 0
  // 空函数不会走进循环
  while (i < length) {
    // 只要有一个值不符合callback预期就返回false
    if (i in this && !callback.call(thisCtx, this[ i ], i, this)) {
      return false
    }

    i++
  }

  return true
}

Test a handful

still use examples to test


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

Basic use

some method tests whether at least one element in the array has passed the provided function test. It returns a Boolean value. mdn

Note

  1. callback will only be called on indexes that "have a value", and will not be called on indexes that have been deleted or have never been assigned.

for example


let emptyArr = []
// 空数组直接返回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

Code

Click to view the source code to achieve

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
}

Test a handful


let emptyArr = []
// 空数组直接返回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

Basic use

filter method creates a new array that contains all the elements that pass the provided function test. mdn

Note

  1. filter is called once for each element in the array callback function, and using all such callback return true or equivalent to the true value elements to create a new array.
  2. callback will only be called on indexes that have been assigned, and will not be called on indexes that have been deleted or have never been assigned.
  3. Those elements that fail the callback test will be skipped and will not be included in the new array.
// 索引为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 ]

Code

Click to view the source code to achieve

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
}

test


// 索引为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

Basic use

reduce reducer function (executed in ascending order) provided by you for each element in the array, and aggregates the results into a single return value mdn

This function is a bit more complicated, let's use an example to see how it is used.


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 (退出)

Code

Click to view the source code to achieve

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
}

Test a handful

const sum = [1, 2, 3, 4].reduce2((prev, cur) => {
  return prev + cur;
})

console.log(sum) // 10

7. reduceRight

Basic use

reduceRight reducer function (executed in descending order) provided by you for each element in the array, and aggregates the results into a single return value mdn

Similar to reduce, the only difference is that reduceRight traverses from right to left

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

Code

Click to view the source code to achieve

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
}

Test a handful

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

Lookup class

8. find

Basic use

find method returns the value of the first element in the array that satisfies the test function. Otherwise return undefined , mdn

be careful

  1. find callback function once for each element in the array until a callback returns true
  2. When such an element is found, the method will immediately return the value of this element, otherwise it will return undefined
  3. callback  function will be called for each index in the array, from to length - 1 , not just those indexes that are assigned. (This point is different from the previous functions)
let arr = [ 0, 1, 2, 3, 4,, 5 ]

let index = arr.find((it) =>  {
  return it > 3
}, { name: '前端胖头鱼' })

console.log(index) // 4

Code

Click to view the source code to achieve


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回调函数的逻辑,就返回元素value
    if (callback.call(thisCtx, value, i, this)) {
      return value
    }

    i++
  }
  // 否则返回undefined  
  return undefined
}

Test a handful


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

image.png

9. findIndex

Basic use

findIndex index of the first element in the array that satisfies the provided test function. If no corresponding element is found, -1 is returned. mdn

The difference from the find function is that findIndex returns the instead of the value . Note that it is basically the same as find

  1. findIndex callback function once for each array index 0 ~ length-1 (including) in the array until it finds a callback function returns true.
  2. If such an element is found, findIndex will immediately return the index of the element. If the callback never returns a true value, or the length of the array is 0, then findIndex returns -1
  3. Unlike some other array methods (such as Array#some), in a sparse array, the callback function is called even for the index of an entry that does not exist in the array
let arr = [ 0, 1, 2, 3, 4,, 5 ]

let index = arr.findIndex((it, i, array) => {
  return it > 2
})

console.log(index) // 3

Code

Click to view the source code to achieve

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
}

Test a handful

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

image.png

10. indexOf

Basic use

indexOf method returns the first index at which a given element can be found in the array, or -1 if it does not exist. mdn
arr.indexOf(searchElement[, fromIndex])

Note

  1. If the index value at the beginning of the search is greater than or equal to the length of the array, it means that it will not be searched in the array and returns -1
  2. If the index value provided in the parameter is a negative value , it will be used as an offset at the end of the array, that is, -1 means searching from the last element, -2 means searching from the penultimate element, and so on
  3. If the index value provided in the parameter is a negative value, the search order is not changed, and the search order is still to query the array from front to back
  4. If the offset index value is still less than 0, the entire array will be queried. Its default value is 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

Code

Click to view the source code to achieve

With the above points of attention and basic use, you will know how to write at a glance.

Array.prototype.indexOf2 = function (targetEle, fromIndex) {
  const length = this.length

  fromIndex = +fromIndex || 0

  // 数组为空或者从大于等于数组长度的地方开始检索,都直接是-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) {
    // 在数组内的元素并且和targetEle强等
    if (i in this && targetEle === this[ i ]) {
      return i
    }

    i++
  }

  return -1
}

Test a handful


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

11. lastIndexOf

Basic use

lastIndexOf method returns the last index of the specified element in the array, or -1 if it does not exist. mdn
arr.lastIndexOf(searchElement[, fromIndex])

Note

  1. Start the reverse search from the arr.length - 1
  2. If fromIndex greater than or equal to the length of the array, the entire array will be searched.
  3. If fromIndex is negative, treat it as an offset from the end of the array forward. Even if the value is negative, the array will still be searched from back to front.
  4. If the fromIndex is negative and its absolute value is greater than the length of the array, the method returns -1, that is, the array will not be searched.
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

Code

Click to view the source code to achieve

Array.prototype.lastIndexOf2 = function (targetEle, fromIndex) {
  const length = this.length

  fromIndex = typeof fromIndex === 'undefined' ? length - 1 : fromIndex
  // 数组为空,以及该值为负时且绝对值大于数组长度,则方法返回 -1,即数组不会被查找。
  if (length === 0 || fromIndex < 0 && Math.abs(fromIndex) >= length) {
    return -1
  }

  let i

  if (fromIndex >= 0) {
    // 如果`fromIndex`大于或等于数组的长度,则整个数组会被查找。
    // 也就是当大于数组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
}

Test a handful


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

12. includes

Basic use

includes method is used to determine whether an array contains a specified value, if it contains, it returns true, otherwise it returns false. mdn
arr.includes(valueToFind[, fromIndex])

Note

  1. From fromIndex index Find valueToFind .
  2. If it is a negative value, start searching from the index of array.length + fromIndex
  3. If there is NaN in the array, [..., NaN ].includes(NaN) is 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

Code

Click to view the source code to achieve

Array.prototype.includes2 = function (targetEle, fromIndex) {
  const length = this.length

  fromIndex = +fromIndex || 0

  // 数组为空或者从大于等于数组长度的地方开始检索,都直接是-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
}

Test a handful


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

Additions, deletions and modifications

13. push

Basic use

push method adds one or more elements to the end of the array and returns the new length of the array. 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

Code

Click to view the source code to achieve


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
}

Test a handful

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

14. pop

Basic use

pop method deletes the last element from the array and returns the value of that element. This method changes the length of the array. mdn
let arr = [ 1, 2 ]
let arr2 = []

console.log(arr.pop(), arr) // 2 [1]
console.log(arr2.pop(), arr2) // undefined []

The code implementation is as simple as the use, just return the last element of the array and reduce the length of the array by 1.

Code

Click to view the source code to achieve

Array.prototype.pop2 = function () {
  const length = this.length
  // 空数组上pop,直接返回undefined
  if (length === 0) {
    return undefined
  }

  const delEle = this[ length - 1 ]

  this.length = length - 1

  return delEle
}

Test a handful

let arr = [ 1, 2 ]
let arr2 = []

console.log(arr.pop2(), arr) // 2 [1]
console.log(arr2.pop2(), arr2) // undefined []

15. unshift

Basic use

unshift method of one or more elements to the array beginning , and returns the array new length (the method modifies the original array ) .

Note

  1. If multiple parameters are passed in, they will be inserted at the beginning of the object in the form of blocks, and their order is the same as the order when passed as parameters.
  2. unshift once with multiple parameters unshift multiple times with one parameter (for example, loop call), they will get different results. E.g:
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]

Code

Click to view the source code to achieve

Array.prototype.unshift2 = function (...unshiftEles) {
  // 借助扩展符,将需要添加的元素以块的形式插入到数组前面
  let newArray = [ ...unshiftEles, ...this ]
  let length = newArray.length
  
  let i = 0

  if (unshiftEles.length === 0) {
    return length
  }
  // 重新复制给数组
  while (i < length) {
    this[ i ] = newArray[ i ]
    i++
  }
  
  return this.length
}

Test a handful


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]

16. shift

Basic use

shift method removes from the array first element, and returns the value of the element. mdn

let arr = [ 1, 2 ]

console.log(arr.shift(), arr) // 1 [2]
console.log(arr.shift(), arr) // 2 []

Code

Click to view the source code to achieve

Array.prototype.shift2 = function () {
  const length = this.length
  const delValue = this[ 0 ]

  let i = 1

  while (i < length) {
    // 从第一个元素开始,后面的元素都往前移动一位
    this[ i - 1 ] = this[ i ]
    i++
  }
  // 设置好数组的长度
  this.length = length - 1
  // 返回删除的值
  return delValue
}

Test a handful


let arr = [ 1, 2 ]

console.log(arr.shift2(), arr) // 1 [2]
console.log(arr.shift2(), arr) // 2 []

17. reverse

Basic use

reverse method reverses the position of the elements in the array and returns the array. That is, the first element of the array will become the last, and the last element of the array will become the first. mdn
const arr = [1, 2, 3]

console.log(arr) // [1, 2, 3]

arr.reverse()

console.log(arr) // [3, 2, 1]

Code

Click to view the source code to achieve

Array.prototype.reverse2 = function () {
  // 设置双指针,往中间靠拢
  let i = 0
  let j = this.length - 1

  while (i < j) {
    // 第一个和最后一个,第二个和倒数第二个进行位置调换
    [ this[ i ], this[ j ] ] = [ this[ j ], this[ i ] ]
    i++
    j--
  }

  return this
}

Test a handful


const arr = [1, 2, 3]

console.log(arr) // [1, 2, 3]

arr.reverse2()

console.log(arr) // [3, 2, 1]

18. fill

Basic use

fill method fills all elements in an array from the start index to the end index with a fixed value. Does not include the termination index. 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]

Code

Click to view the source code to achieve

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++
  }
  // 返回被修改的数组
  return this
}

Test a handful


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]

Connection, splicing

19. concat

Basic use

concat method is used to merge two or more arrays. This method does not change the existing array, but returns a new array 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]]

Code

Click to view the source code to achieve

Array.prototype.concat2 = function (...concatEles) {
  const length = concatEles.length
  // 数组本身展开一层
  let newArray = [ ...this ]
  let i = 0

  while (i < length) {
    const value = concatEles[ i ]
    // 对数组元素展开一层 
    Array.isArray(value) ? newArray.push(...value) : newArray.push(value)
    i++
  }

  return newArray
}

Test a handful


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]]

20. join

Basic use

join method concatenates all the elements of an array character identifier and returns this string. If the array has only one item, then that item will be returned without using the separator.
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

Code

Click to view the source code to achieve

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
}

Test a handful

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

Static method

21. Array.isArray

Basic use

Array.isArray() used to determine whether the passed value is a Array .

Array.isArray([1, 2, 3]) // true

Array.isArray({foo: 123}) // false

Array.isArray("foobar") // false

Array.isArray(undefined) // false

Code

Click to view the source code to achieve

This is very simple, it only takes one sentence

Array.isArray2 = function (ele) {
  return  Object.prototype.toString.call(ele) === '[object Array]';
}

Test a handful


Array.isArray2([1, 2, 3]) // true

Array.isArray2({foo: 123}) // false

Array.isArray2("foobar") // false

Array.isArray2(undefined) // false

22. Array.of

Basic use

Array.of method creates a new array instance with a variable number of parameters, regardless of the number or type of parameters.

Note

Array.of() and Array constructors is the handling of integer parameters:

Array.of(7) creates an array with a single element 7 , and Array(7) creates an empty array with a length of 7 ( Note: This refers to an array with 7 empty positions ( undefined Array)

Array.of(7);       // [7]
Array.of(1, 2, 3); // [1, 2, 3]

Array(7);          // [ , , , , , , ]
Array(1, 2, 3);    // [1, 2, 3]

Code

Click to view the source code to achieve

The realization idea is to assign the values you pass in to the current array one by one.

Array.of2 = function (...eles) {
  const length = eles.length
  let i = 0
  let newArray = []

  while (i < length) {
    newArray[ i ] = eles[ i ]
    i++
  }

  return newArray
}

Test a handful


Array.of2(7);       // [7]
Array.of2(1, 2, 3); // [1, 2, 3]

Flat class

23. flat

Basic use

flat() method will recursively traverse the array according to a specified depth, and merge all the elements with the elements in the traversed sub-array into a new array and return. 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]] 指定展开两层

Code

Click to view the source code to achieve


Array.prototype.flat2 = function (depth = 1) {
  const result = []
  const flat = (arr, depth) => {
    for (let item of arr) {
      // 当层数还未全部展开的时候,进行递归处理
      if (Array.isArray(item) && depth > 0) {
        flat(item, depth - 1)
      } else {
        // 去除空元素,添加非undefined元素
        item !== void 0 && result.push(item)
      }
    }
  }

  flat(this, depth)

  return result
}

Test a handful


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]] 

24. flatMap

Basic use

flatMap method first uses the mapping function to map each element, and then compresses the result into a new array. It is almost the same as map flat depth value of 1. mdn

let arr = [1, 2, 3, 4]


arr.flatMap(x => [x * 2]) // [2, 4, 6, 8]

Code

Click to view the source code to achieve


Array.prototype.flatMap2 = function (callback, thisCtx) {
  if (typeof callback !== 'function') {
    throw `${callback} is not a function`
  }
  // map和flat具体实现可以看map.js和flat.js
  return this.map(function (it, i, array) {
    return callback.call(thisCtx, it, i, array)
  }).flat(1)
}

test

let arr = [1, 2, 3, 4]


arr.flatMap2(x => [x * 2]) // [2, 4, 6, 8]

end

National Day is approaching, I wish you all a happy holiday and seven days of joy.

The article may contain problems or insufficient implementation. You are welcome to point out in the comment area, and you must make corrections without stopping. Thanks.

Due to the length of the article, there are still many array methods that have not been written in the article. If they are of some use to you, we will splice follow-up on the original implementation of the remaining functions such as 0617205b0da9ba, keys , values Good night everyone 🌹


前端胖头鱼
3.7k 声望6.2k 粉丝