JavaScript で 24 以上の配列メソッドを手動で実装する

JavaScript で 24 以上の配列メソッドを手動で実装する

この記事では、24 以上のネイティブ配列メソッドの内部実装について説明します。この記事を読めば、何か違ったものが得られると思います。

1. トラバーサルクラス

1. 各

基本的な使い方:

forEachは非常に一般的なトラバーサル関数なので、よく知っておく必要があります。ここでは、重要でありながら見落とされがちないくつかの点に焦点を当てます。中文

  • このメソッドは、配列の各要素に対して指定された関数を1回実行し、戻り値はundefiendです。
  • このメソッドは、有効な値を持つ配列内の各項目に対して、昇順でcallback関数を 1 回実行します。初期化されていない項目はスキップされます (たとえば、スパース配列の場合)。
  • 既存の値が変更された場合、 callbackに渡される値はforEach()が反復処理した時点での値になります。
  • 削除されたアイテムは走査されません

ここに小さな例を示します。

demoArr = [ 1, 2, 3, 4, , 5 ]とします。

デモArr.forEach((it, i) => {
  もし (i === 1) { 
    // 後で追加されたものはdemoArr.push(5)ではアクセスされません
  } そうでない場合 (i === 2) {
    // 4 はアクセスされませんが、4-4 はアクセスされます demoArr.splice(3, 1, '4-4')
  }

  コンソールログ(それ)
})

/*
 1
 2
 3
 4-4
 5
*/

コード実装:

Array.prototype.forEach2 = 関数 (コールバック、thisCtx) {
  if (typeof コールバック !== 'function') {
    `${callback} は関数ではありません` をスローします
  }

  定数長さ = this.length
  i = 0とする

  (i < 長さ) の間 {
    // 削除され、新しく追加された要素のインデックス i は配列にないので、(i in this) の場合はアクセスされません。
      コールバック.call(thisCtx, this[ i ], i, this)
    }

    私は++
  }
}

前と同じ例を使用すると、変更後の出力は同じになります。

テストしてみましょう:

// テスト let demoArr = [ 1, 2, 3, 4, , 5 ]

デモArr.forEach2((it, i) => {
  もし (i === 1) {
    // 後で追加されたものはdemoArr.push(5)ではアクセスされません
  } そうでない場合 (i === 2) {
    // 4 はアクセスされませんが、同様に 4-4 はアクセスされます demoArr.splice(3, 1, '4-4')
  }

  コンソールログ(それ)
})

/*
 1
 2
 3
 4-4
 5
*/

2. 地図

基本的な使い方:

mapメソッドは、各要素が指定された関数を 1 回呼び出した戻り値である新しい配列を作成します。 mdn

注記:

  • callback関数は、値を持つインデックスに対してのみ呼び出されます。
  • 値が割り当てられていない、または delete を使用して削除されていないインデックスは呼び出されません。
// インデックス 2 には値が割り当てられていないことに注意してください。let arr = [ 1, 2, ,4, 5 ]

// インデックス3を削除
削除arr[3]

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

コード実装:

ソースコードの実装を表示するにはクリックしてください

Array.prototype.map2 = 関数 (コールバック、thisCtx) {
  if (typeof コールバック !== 'function') {
    `${callback} は関数ではありません` をスローします
  }

  定数長さ = this.length
  i = 0とする
  // mapの戻り値は新しい配列です。let newArray = []

  (i < 長さ) の間 {
    // 削除されたものや初期化されていないものは走査されません if (i in this) {
      newArray.push(callback.call(thisCtx, this[ i ], i, this))
    }

    私は++
  }
  // 新しい配列を返す return newArray
}



テストしてみましょう:

arr = [ 0, 1, 2, 3, 4,, 5 ]とします。

arr2 = arr.map2(関数 (it, i, 配列) {
  console.log(it, i, 配列, this)
  返す * それ
}, { name: 'フロントエンド ファットヘッド フィッシュ' })

コンソールログ(arr2)

3. すべての

基本的な使い方:

everyメソッドは、配列内のすべての要素が指定された関数のテストに合格するかどうかをテストします。ブール値を返します。 mdn

注記:

  • 空の配列を受け取った場合、このメソッドは常に true を返します。
  • コールバックは、値が割り当てられたインデックスに対してのみ呼び出されます。
  • 削除されたインデックスや値が割り当てられていないインデックスに対しては呼び出されません。
// 例 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)) // 真

コード実装:

ソースコードの実装を表示するにはクリックしてください

Array.prototype.every2 = 関数 (コールバック、thisCtx) {
  if (typeof コールバック !== 'function') {
    `${callback} は関数ではありません` をスローします
  }

  定数長さ = this.length
  i = 0とする
  // 空の関数はループに入りません while (i < length) {
    // 1つの値がコールバックの期待値を満たさない限り、falseを返します
    if (i が this にある && !callback.call(thisCtx, this[ i ], i, this)) {
      偽を返す
    }

    私は++
  }

  真を返す
}

テストしてみましょう:

例をあげてテストしてみましょう

空のArr = []とする

console.log(emptyArr.every2((it) => it > 0)) // 真

arr = [ 0, 1, 2, 3, 4,, 5, -1 ] とします。

削除arr[7]

console.log(arr.every2((it) => it >= 0)) // 真



4. いくつか

基本的な使い方:

someメソッドは、指定された関数のテストに合格する要素が配列内に少なくとも 1 つあるかどうかをテストします。 Boolean値を返します。中文

注記:

  • callback 、「値を持つ」インデックスに対してのみ呼び出され、削除されたインデックスや値が割り当てられていないインデックスに対しては呼び出されません。

例えば

空のArr = []とする
// 空の配列は直接falseを返します
console.log(emptyArr.some((it) => it > 0)) // false
arr = [ 0, 1, 2, 3, 4,, 5, -1 ] とします。
// トラバーサルの前に -1 を削除します。0 未満の値しか存在しないため、false を返します。
削除arr[7]

console.log(arr.some((it) => it < 0)) // false

コード実装:

ソースコードの実装を表示するにはクリックしてください

Array.prototype.some2 = 関数 (コールバック、thisCtx) {
  if (typeof コールバック !== 'function') {
    `${callback} は関数ではありません` をスローします
  }

  定数長さ = this.length
  i = 0とする

  (i < 長さ) の間 {
    // コールバック条件を満たす要素がある限り、true を返します
    if (i in this && callback.call(thisCtx, this[ i ], i, this)) {
      真を返す
    }

    私は++
  }

  偽を返す
}

テストしてみましょう:

空のArr = []とする
// 空の配列は直接trueを返します
console.log(emptyArr.some2((it) => it > 0)) // 偽
arr = [ 0, 1, 2, 3, 4,, 5, -1 ] とします。

削除arr[7]

console.log(arr.some2((it) => it < 0)) // 偽
console.log(arr.some2((it) => it > 0)) // 真

5. フィルター

基本的な使い方:

filterメソッドは、指定された関数テストに合格したすべての要素を含む新しい配列を作成します。中文

注記:

  • filter配列内の各要素に対してcallback関数を 1 回呼び出し、 callback trueまたはtrueと同等の値を返すすべての要素を含む新しい配列を作成します。
  • callback 、値が割り当てられたインデックスに対してのみ呼び出され、削除されたインデックスや値が割り当てられていないインデックスに対しては呼び出されません。
  • callbackテストに失敗した要素はスキップされ、新しい配列には含まれません。
// インデックス 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 ]

コード実装:

ソースコードの実装を表示するにはクリックしてください

Array.prototype.filter2 = 関数 (コールバック、thisCtx) {
  if (typeof コールバック !== 'function') {
    `${callback} は関数ではありません` をスローします
  }

  定数長さ = this.length
  新しい配列を [] にする
  i = 0とする

  (i < 長さ) の間 {
    if (i in this && callback.call(thisCtx, this[ i ], i, this)) {
      newArray.push(this[ i ])
    }
    私は++
  }

  新しい配列を返す
}

テスト:

// インデックス 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メソッドは、配列内の各要素に対して指定されたreducer関数を(昇順で)実行し、結果を 1 つの戻り値にまとめます。

この関数は少し複雑です。例を使って使い方を見てみましょう。

定数sum = [1, 2, 3, 4].reduce((prev, cur) => {
  prev + cur を返します。
})

コンソール.log(合計) // 10

// 初期設定 prev = initialValue = 1、cur = 2

// 最初の反復 prev = (1 + 2) = 3、cur = 3

// 2 回目の反復 prev = (3 + 3) = 6、cur = 4

// 3 回目の反復 prev = (6 + 4) = 10、cur = undefined (終了)

コード実装:

ソースコードの実装を表示するにはクリックしてください

Array.prototype.reduce2 = 関数 (コールバック、initValue) {
  if (typeof コールバック !== 'function') {
    `${callback} は関数ではありません` をスローします
  }

  pre = initValue とします
  i = 0とする
  定数長さ = this.length
  // 初期値が渡されない場合は、最初の値を初期値として取得します。if (typeof pre === 'undefined') {
    前 = これ[0]
    私 = 1
  }

  (i < 長さ) の間 {
    もし(私がこれに){
      pre = コールバック(pre, this[ i ], i, this)
    }
    私は++
  }

  戻る前
}

テスト:

定数sum = [1, 2, 3, 4].reduce2((prev, cur) => {
  prev + cur を返します。
})

コンソール.log(合計) // 10

7. 右を減らす

基本的な使い方:

reduceRightメソッドは、配列内の各要素に対して(降順で)指定されたreducer関数を実行し、結果を単一の戻り値mdnに集約します。

非常にreduceに似ていますが、唯一の違いはreduceRight右から左に移動する点です。

定数sum = [1, 2, 3, 4].reduce((prev, cur) => {
  コンソールログ(現在)
  prev + cur を返します。
})

// 21
// 3 2
// 4 3

コンソール.log(合計) // 10

const sum2 = [1, 2, 3, 4].reduceRight((prev, cur) => {
  コンソールログ(現在)
  prev + cur を返します。
})
// 3 2 
// 21
// 1 0

コンソール.log(合計2) // 10

コード実装:

ソースコードの実装を表示するにはクリックしてください

Array.prototype.reduceRight2 = 関数 (コールバック、initValue) {
  if (typeof コールバック !== 'function') {
    `${callback} は関数ではありません` をスローします
  }

  pre = initValue とします
  定数長さ = this.length
  // 最後の要素から走査を開始する let i = length - 1
  // 初期値が渡されない場合は、最後の値が初期値として使用されます if (typeof pre === 'undefined') {
    pre = これ[i]
    私 - 
  }

  i >= 0 の間
    もし(私がこれに){
      pre = コールバック(pre, this[ i ], i, this)
    }
    私 - 
  }

  戻る前
}

テスト:

定数合計 = [1, 2, 3, 4].reduceRight2((prev, cur) => {
  コンソールログ(現在)
  prev + cur を返します。
})

// 3 2
// 21
// 1 0

コンソール.log(合計) // 10

2. クラスの検索

1. 見つける

基本的な使い方:

find メソッドは、テスト関数を満たす配列の最初の要素の値を返します。それ以外の場合はundefined 、 mdn を返します。

注記:

  • findメソッドは、配列内の各要素に対してcallback関数を1回実行し、1つのcallback trueを返すまで実行します。
  • そのような要素が見つかった場合、メソッドはすぐに要素の値を返し、そうでない場合はundefinedを返します。
  • callback関数は、値が割り当てられているインデックスだけでなく、 0 からlength - 1の配列内のすべてのインデックスに対して呼び出されます。 (この点がこれまでの機能と異なります)
arr = [ 0, 1, 2, 3, 4,, 5 ]とします。

インデックスをarr.find((it) => {とする
  返す > 3
}, { name: 'フロントエンド ファットヘッド フィッシュ' })

コンソール.log(インデックス) // 4

コード実装:

Array.prototype.find2 = 関数 (コールバック、thisCtx) {
  if (typeof コールバック !== 'function') {
    `${callback} は関数ではありません` をスローします
  }

  定数長さ = this.length
  i = 0とする

  (i < 長さ) の間 {
    定数値 = this[ i ]
    // コールバック関数のロジックを満たす要素がある限り、要素の値が返されます
    if (callback.call(thisCtx, value, i, this)) {
      戻り値
    }

    私は++
  }
  // それ以外の場合は undefined を返します  
  未定義を返す
}

テスト:

arr = [ 0, 1, 2, 3, 4,, 5 ]とします。

インデックス = arr.find2(関数 (it, i, 配列) {
  console.log(it, i, 配列, this)
  返す > 3
}, { name: 'フロントエンド ファットヘッド フィッシュ' })

コンソール.log(インデックス) // 4

2. インデックスを見つける

基本的な使い方:

  • findIndexメソッドは、指定されたテスト関数を満たす配列内の最初の要素のインデックスを返します。対応する要素が見つからない場合は -1 が返されます。中文
  • find関数との違いは、 findIndex値ではなくインデックスを返すことです。注意すべき点は基本的にfindと同じです。
  • findIndex メソッドは、 callback関数が true を返す値が見つかるまで、配列内の配列インデックス 0 から length-1 (含む) までの各配列インデックスに対してコールバック関数を 1 回実行します。
  • そのような要素が見つかった場合、findIndex は直ちにその要素のインデックスを返します。コールバックが true 値を返さない場合、または配列のlengthが 0 の場合、 findIndex -1 を返します。
  • 他の配列メソッド ( Array#someなど) とは異なり、スパース配列では、配列内に存在しないエントリのインデックスに対してもコールバック関数が呼び出されます。
arr = [ 0, 1, 2, 3, 4,, 5 ]とします。

インデックスをarr.findIndex((it, i, 配列) => {
  返す > 2
})

コンソール.log(インデックス) // 3

コード実装:

ソースコードの実装を表示するにはクリックしてください

Array.prototype.findIndex2 = 関数 (コールバック、thisCtx) {
  if (typeof コールバック !== 'function') {
    `${callback} は関数ではありません` をスローします
  }

  定数長さ = this.length
  i = 0とする

  (i < 長さ) の間 {
    // コールバックロジックに従ってインデックス i を直接返します
    (コールバックを呼び出します(thisCtx、this[i]、i、this)){
      戻る
    }

    私は++
  }
  // それ以外の場合は -1 を返す  
  -1を返す
}

テスト:

arr = [ 0, 1, 2, 3, 4,, 5 ]とします。

index = arr.findIndex2(関数 (it, i, 配列) {
  console.log(it, i, 配列, this)
  返す > 2
}, { name: 'フロントエンド ファットヘッド フィッシュ' })

コンソール.log(インデックス) // 3

3. インデックス

基本的な使い方:

indexOfメソッドは、指定された要素が見つかる配列の最初のインデックスを返します。存在しない場合は -1 を返します。中文

arr.indexOf(searchElement[, fromIndex])

注記:

  • 検索を開始するインデックス値が配列の長さ以上の場合は、配列内で検索は実行されず、-1 が返されます。
  • パラメータで指定されたインデックス値が負の値の場合、配列の末尾からのオフセットとして扱われます。つまり、-1 は最後の要素から開始することを意味し、-2 は最後から 2 番目の要素から開始することを意味します。
  • パラメータで指定されたインデックス値が負の値の場合、検索順序は変更されません。検索順序は、配列を前から後ろへ検索する順序のままです。
  • オフセット インデックスがまだ 0 未満の場合、配列全体が照会されます。デフォルト値は 0 です。
定数配列 = [2, 5, 9]

コンソール.log(配列.indexOf(2)) // 0
console.log(配列.indexOf(7)) // -1
コンソール.log(配列.indexOf(9, 2)) // 2
console.log(配列.indexOf(2, -1)) // -1
コンソール.log(配列.indexOf(2, -3)) // 0

コード実装:

ソースコードの実装を表示するにはクリックしてください

以上のポイントと基本的な使い方を押さえておけば、一目で書き方がわかるはずです。

Array.prototype.indexOf2 = 関数 (targetEle, fromIndex) {
  定数長さ = this.length

  fromIndex = +fromIndex || 0

  // 配列が空の場合、または検索が配列の長さ以上の位置から開始される場合、値は -1 になります。
  if (長さ === 0 || fromIndex >= 長さ) {
    -1を返す
  }
  /*
    1. fromIndex から要素の検索を開始します 2. fromIndex が 0 より大きい場合は、そのまま取得します 3. 0 より小さい場合は、まず長さから fromIndex の絶対値を減算します。それでも 0 より小さい場合は、そのまま 0 を取得します*/
  i = Math.max(fromIndex >= 0 ? fromIndex : length - Math.abs(fromIndex), 0) とします。

  (i < 長さ) の間 {
    // 配列内の要素で targetEle と等しいもの if (i in this && targetEle === this[ i ]) {
      戻る
    }

    私は++
  }

  -1を返す
}

テスト:

定数配列 = [2, 5, 9]

コンソール.log(配列.indexOf2(2)) // 0
コンソール.log(配列.indexOf2(7)) // -1
コンソール.log(配列.indexOf2(9, 2)) // 2
console.log(配列.indexOf2(2, -1)) // -1
コンソール.log(配列.indexOf2(2, -3)) // 0

4. 最後のインデックス

基本的な使い方:

lastIndexOfメソッドは、配列内の指定された要素の最後のインデックスを返します。存在しない場合は -1 を返します。中文

arr.lastIndexOf(searchElement[, fromIndex])

注記:

  • arr.length - 1位置から逆方向に検索を開始します。
  • fromIndex配列の長さ以上の場合は、配列全体が検索されます。
  • fromIndexが負の場合、配列の末尾からのオフセットとして扱われます。値が負の場合でも、配列は後ろから前に向かって検索されます。
  • fromIndex値が負で、その絶対値が配列の長さより大きい場合、メソッドは -1 を返します。これは、配列が検索されないことを意味します。
配列 = [2, 5, 9, 2] とします

コンソール.log(配列.lastIndexOf(2)) // 3
console.log(配列.lastIndexOf(7)) // -1
console.log(配列.lastIndexOf(2, 3)) // 3
コンソール.log(配列.lastIndexOf(2, 2)) // 0
console.log(配列.lastIndexOf(2, -2)) // 0
コンソール.log(配列.lastIndexOf(2, -1)) // 3

コード実装:

ソースコードの実装を表示するにはクリックしてください

Array.prototype.lastIndexOf2 = 関数 (targetEle, fromIndex) {
  定数長さ = this.length

  fromIndex = typeof fromIndex === 'undefined' ? 長さ - 1 : fromIndex
  // 配列が空の場合、または値が負でその絶対値が配列の長さより大きい場合、メソッドは -1 を返します。これは、配列が検索されないことを意味します。
  if (長さ === 0 || fromIndex < 0 && Math.abs(fromIndex) >= 長さ) {
    -1を返す
  }

  私は

  if (fromIndex >= 0) {
    // `fromIndex` が配列の長さ以上の場合は、配列全体が検索されます。
    // つまり、配列の長さ - 1 より大きい場合は、長さ - 1 が取得されます
    i = Math.min(fromIndex, 長さ - 1)
  } それ以外 {
    i = 長さ - Math.abs(fromIndex)
  }

  i >= 0 の間
    // targetEle と等しい場合はインデックスを返します if (i in this && targetEle === this[ i ]) {
      戻る
    }
    // 逆トラバーサル i--
  }
  // 見つからない場合は -1 を返す
  -1を返す
}

テスト:

配列 = [2, 5, 9, 2] とします

コンソール.log(配列.lastIndexOf2(2)) // 3
console.log(配列.lastIndexOf2(7)) // -1
コンソール.log(配列.lastIndexOf2(2, 3)) // 3
コンソール.log(配列.lastIndexOf2(2, 2)) // 0
コンソール.log(配列.lastIndexOf2(2, -2)) // 0
コンソール.log(配列.lastIndexOf2(2, -1)) // 3

5. 含まれるもの

基本的な使い方:

includesメソッドは、配列に指定された値が含まれているかどうかを判断するために使用されます。含まれている場合は true を返し、含まれていない場合はfalseを返します。中文

arr.includes(valueToFind[, fromIndex])

注記:

  • fromIndex インデックスからvalueToFindを検索します。
  • 負の値の場合、検索はarray.length + fromIndexのインデックスから昇順で開始されます。
  • 配列にNaNがある場合,[ ..., NaN ].includes(NaN )はtrueになります。
console.log([1, 2, 3].includes(2)) // 真
console.log([1, 2, 3].includes(4)) // 偽
console.log([1, 2, 3].includes(3, 3)) // 偽
console.log([1, 2, 3].includes(3, -1)) // 真
console.log([1, 2, NaN].includes(NaN)) // 真

コード実装:

ソースコードの実装を表示するにはクリックしてください

Array.prototype.includes2 = 関数 (targetEle, fromIndex) {
  定数長さ = this.length

  fromIndex = +fromIndex || 0

  // 配列が空の場合、または検索が配列の長さ以上の位置から開始される場合、値は -1 になります。
  if (長さ === 0 || fromIndex >= 長さ) {
    偽を返す
  }
  /*
    1. fromIndex から要素の検索を開始します 2. fromIndex が 0 より大きい場合は、そのまま取得します 3. 0 より小さい場合は、まず長さから fromIndex の絶対値を減算します。それでも 0 より小さい場合は、そのまま 0 を取得します*/
  i = Math.max(fromIndex >= 0 ? fromIndex : length - Math.abs(fromIndex), 0) とします。

  (i < 長さ) の間 {
    定数値 = this[ i ]
    // NaN 状況に注意してください if (targetEle === value || typeof targetEle === 'number' && typeof value === 'number' && isNaN(targetEle) && isNaN(value)) {
      真を返す
    }

    私は++
  }

  偽を返す
}

テスト:

console.log([1, 2, 3].includes2(2)) // 真
console.log([1, 2, 3].includes2(4)) // 偽
console.log([1, 2, 3].includes2(3, 3)) // 偽
console.log([1, 2, 3].includes2(3, -1)) // 真
console.log([1, 2, NaN].includes2(NaN)) // 真

3. 追加、削除、変更

1. 押す

基本的な使い方:

pushメソッドは、配列の末尾に 1 つ以上の要素を追加し、配列の新しい長さを返します。中文

const 動物 = ['豚', 'ヤギ', '羊']
動物.push('牛')

console.log(動物, 動物の長さ) 
// ["豚", "ヤギ", "羊", "牛"], 4

animals.push('鶏', '猫', '犬')

console.log(動物, 動物の長さ) 

// ["豚", "ヤギ", "羊", "牛", "鶏", "猫", "犬"], 7

コード実装:

ソースコードの実装を表示するにはクリックしてください

Array.prototype.push2 = 関数 (...pushEles) {
  定数pushEleLength = pushEles.length
  定数長さ = this.length

  i = 0とする
  
  (i < プッシュエレメント長) {
    this[長さ + i] = pushEles[i]
    私は++
  }

  this.lengthを返す
}

テスト:

const 動物 = ['豚', 'ヤギ', '羊']
動物.push2('牛')

console.log(動物, 動物の長さ) 
// ["豚", "ヤギ", "羊", "牛"], 4

animals.push2('鶏', '猫', '犬')

console.log(動物, 動物の長さ) 

// ["豚", "ヤギ", "羊", "牛", "鶏", "猫", "犬"], 7

2. ポップ

基本的な使い方:

pop メソッドは配列から最後の要素を削除し、その要素の値を返します。このメソッドは配列の長さを変更します。中文

arr = [ 1, 2 ] とします。
arr2 = []とする

console.log(arr.pop(), arr) // 2 [1]
console.log(arr2.pop(), arr2) // 未定義 []

コードは、使用方法と同じくらい実装も簡単です。配列の最後の要素を返して、配列の長さを 1 減らすだけです。

コード実装:

ソースコードの実装を表示するにはクリックしてください

Array.prototype.pop2 = 関数 () {
  定数長さ = this.length
  // 空の配列をポップし、直接 undefined を返します
  長さ === 0 の場合 {
    未定義を返す
  }

  const delEle = this[長さ - 1]

  this.length = 長さ - 1

  戻り値 delEle
}

テスト:

arr = [ 1, 2 ] とします。
arr2 = []とする

コンソール.log(arr.pop2(), arr) // 2 [1]
console.log(arr2.pop2(), arr2) // 未定義 []

3. シフト解除

基本的な使い方:

unshiftメソッドは、配列の先頭に 1 つ以上の要素を追加し、配列の新しい長さを返します (このメソッドは元の配列を変更します)。

注記:

  • 複数の引数が渡された場合、それらは引数として渡されたのと同じ順序で、オブジェクトの先頭にブロックとして挿入されます。
  • 複数の引数を指定して unshift を 1 回呼び出すと、1 つの引数を指定して unshift を複数回呼び出す場合 (たとえば、ループ内) とは異なる結果が生成されます。

例えば:

arr = [4,5,6]とする
// arr.unshift(1,2,3) を一度に挿入する

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

arr2 = [4,5,6]とする
// 複数回挿入 arr2.unshift(1)
arr2.unshift(2)
arr2.unshift(3)

console.log(arr2); // [3, 2, 1, 4, 5, 6]

コード実装:

ソースコードの実装を表示するにはクリックしてください

Array.prototype.unshift2 = 関数 (...unshiftEles) {
  // 拡張演算子を使用して、追加する要素をブロックの形式で配列の先頭に挿入します。let newArray = [ ...unshiftEles, ...this ]
  長さ = newArray.length とする
  
  i = 0とする

  unshiftEles.length === 0 の場合 {
    戻り長さ
  }
  // 配列に再コピー while (i < length) {
    this[ i ] = newArray[ i ]
    私は++
  }
  
  this.lengthを返す
}

テスト:

arr = [4,5,6]とする
// arr.unshift2(1,2,3) を一度に挿入する

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

arr2 = [4,5,6]とする
// 複数回挿入 arr2.unshift2(1)
arr2.unshift2(2)
arr2.unshift2(3)

console.log(arr2); // [3, 2, 1, 4, 5, 6]

4. シフト

基本的な使い方:

shift メソッドは、配列から最初の要素を削除し、その要素の値を返します。中文

arr = [ 1, 2 ] とします。

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

コード実装:

ソースコードの実装を表示するにはクリックしてください

Array.prototype.shift2 = 関数(){
  定数長さ = this.length
  const delValue = this[ 0 ]

  i = 1とする

  (i < 長さ) の間 {
    // 最初の要素から始めて、次の要素は1つ前に移動します。this[ i - 1 ] = this[ i ]
    私は++
  }
  // 配列の長さを設定します this.length = length - 1
  // 削除された値を返す return delValue
}

テスト:

arr = [ 1, 2 ] とします。

コンソール.log(arr.shift2(), arr) // 1 [2]
console.log(arr.shift2(), arr) // 2 []

5. 逆

基本的な使い方:

reverseメソッドは、配列内の要素の位置を反転し、配列を返します。つまり、配列の最初の要素が最後の要素になり、配列の最後の要素が最初の要素になります。中文

```javascript
定数arr = [1, 2, 3]

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

arr.reverse()

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

コード実装:

ソースコードの実装を表示するにはクリックしてください

Array.prototype.reverse2 = 関数 () {
  // ダブルポインタを中央に近づけるように設定する let i = 0
  j = this.length - 1 とします。

  i < j である間 {
    // 最初と最後、2番目と最後から2番目を入れ替えます [ this[ i ], this[ j ] ] = [ this[ j ], this[ i ] ]
    私は++
    じーー
  }

  これを返す
}

テスト:

定数arr = [1, 2, 3]

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

arr.reverse2()

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

6. 埋める

基本的な使い方:

fillメソッドは、配列の開始インデックスから終了インデックスまでのすべての要素を固定値で埋めます。終了インデックスは含まれません。中文

定数配列1 = [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 = 関数 (値、開始、終了) {
  定数長さ = this.length

  開始 = 開始 >> 0
  // end が入力されていない場合は、デフォルトは length です。それ以外の場合は、入力された end = typeof end === 'undefined' ? length : end >> 0
  // 最小開始値は0、最大値は長さです
  開始 = 開始 >= 0 ? Math.min(開始、長さ) : Math.max(開始 + 長さ、0)
  // 終了の最小値は0、最大値は長さです 
  end = end >= 0 ? Math.min(end, length) : Math.max(end + length, 0)
  // 指定された範囲をインデックス値で埋める
  (開始 < 終了) の間 {
    this[開始] = 値
    開始++
  }
  // 変更された配列を返す return this
}

テスト:

定数配列1 = [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メソッドは、2 つ以上の配列を結合するために使用されます。このメソッドは既存の配列を変更せず、新しい配列mdnを返します。

 num1 = [[1]]とする
num2 = [2, [3]]とする
num3=[5,[6]]とする

nums = num1.concat(num2) // [[1], 2, [3]]とします。
nums2 = num1.concat(4, num3) // [[1], 4, 5,[6]]とします。

コード実装:

ソースコードの実装を表示するにはクリックしてください

Array.prototype.concat2 = 関数 (...concatEles) {
  定数長さ = concatEles.length
  // 配列自体を 1 層拡張します。let newArray = [ ...this ]
  i = 0とする

  (i < 長さ) の間 {
    定数値 = concatEles[ i ]
    // 配列要素の 1 つのレイヤーを展開します Array.isArray(value) ? newArray.push(...value) : newArray.push(value)
    私は++
  }

  新しい配列を返す
}

テスト:

num1 = [[1]]とする
num2 = [2, [3]]とする
num3=[5,[6]]とする

nums = num1.concat2(num2) // [[1], 2, [3]]とします。
nums2 = num1.concat2(4, num3) // [[1], 4, 5,[6]]とします。

8. 参加する

基本的な使い方:

joinメソッドは、文字列識別子を使用して配列のすべての要素を文字列に連結し、その文字列を返します。配列に項目が 1 つしかない場合は、その項目は区切り文字なしで返されます。

const elements = ['火', '空気', '水']
const elements2 = ['火']

console.log(elements.join()) // 火、空気、水
console.log(elements.join('')) // 火空気水
console.log(elements.join('-')) // 火-空気-水
console.log(elements2.join('-')) // 発火

コード実装:

ソースコードの実装を表示するにはクリックしてください

Array.prototype.join2 = 関数 (フォーマット = ',') {
  定数長さ = this.length
  // 最後の要素はフォーマット接続に参加しないので保存します。let lastEle = this[length - 1]
  文字列 = ''

  長さ === 0 の場合 {
    文字列を返す
  }

  (i = 0; i < 長さ - 1; i++) の場合 {
    文字列 += this[ i ] + フォーマット
  }

  文字列 + lastEle を返す
}

テスト:

const elements = ['火', '空気', '水']
const elements2 = ['火']

console.log(elements.join2()) // 火、空気、水
console.log(elements.join2('')) // 火空気水
console.log(elements.join2('-')) // 火-空気-水
console.log(elements2.join2('-')) // 発火

4. 静的メソッド

1. Array.isArray

基本的な使い方:

Array.isArray()渡された値が配列であるかどうかを判断するために使用されます。

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

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

Array.isArray("foobar") // false

Array.isArray(未定義) // false

コード実装:

ソースコードの実装を表示するにはクリックしてください

これはとてもシンプルで、たった一文です

Array.isArray2 = 関数 (ele) {
  Object.prototype.toString.call(ele) === '[オブジェクト配列]'を返します。
}

テスト:

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

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

Array.isArray2("foobar") // false

Array.isArray2(未定義) // false

2. 配列.of

基本的な使い方:

Array.ofメソッドは、引数の数や型に関係なく、可変数の引数を持つ新しい配列インスタンスを作成します。

注記:

  • Array.of()と Array コンストラクターの違いは、整数引数の処理にあります。
  • Array.of(7)要素 7 を 1 つ持つ配列を作成しますが、Array(7) は長さ 7 の空の配列を作成します (注意: これは 7 つの未定義値で構成される配列ではなく、7 つの空のスロットを持つ配列を意味します)。
配列.of(7); // [7]
配列.of(1, 2, 3); // [1, 2, 3]

配列(7); // [ , , , , , , ]
配列(1, 2, 3); // [1, 2, 3]

コード実装:

ソースコードの実装を表示するにはクリックしてください

実装のアイデアは、現在の配列に入力した値を 1 つずつ割り当てることです。

Array.of2 = 関数 (...eles) {
  定数長さ = eles.長さ
  i = 0とする
  新しい配列を [] にする

  (i < 長さ) の間 {
    新しい配列[ i ] = 要素[ i ]
    私は++
  }

  新しい配列を返す
}

テスト:

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

5. フラット

1. 平らな

基本的な使い方:

flat()メソッドは、配列を指定された深さまで再帰的に走査し、走査されたサブ配列内のすべての要素を新しい配列にマージして返します。中文

定数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]] は2つのレイヤーを展開することを指定します

コード実装:

ソースコードの実装を表示するにはクリックしてください

Array.prototype.flat2 = 関数 (深さ = 1) {
  定数結果 = []
  const flat = (arr, 深さ) => {
    for (let 項目の arr) {
      // レイヤー数が完全に拡張されていない場合は再帰処理 if (Array.isArray(item) && depth > 0) {
        フラット(アイテム、深さ - 1)
      } それ以外 {
        // 空の要素を削除し、未定義でない要素を追加します item !== void 0 && result.push(item)
      }
    }
  }

  フラット(これ、深さ)

  結果を返す
}

テスト:

定数arr1 = [0, 1, 2, [3, 4]];

console.log(arr1.flat2()) // [0, 1, 2, 3, 4]


定数arr2 = [0, 1, 2, [[[3, 4]]]]

console.log(arr2.flat2(2)) // [0, 1, 2, [3, 4]] 

2. フラットマップ

基本的な使い方:

flatMapメソッドは、まずマッピング関数を使用して各要素をマッピングし、次に結果を新しい配列に圧縮します。深度値1のフラットに接続されたマップとほぼ同じです。中文

arr = [1, 2, 3, 4]とします。


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

コード実装:

ソースコードの実装を表示するにはクリックしてください

Array.prototype.flatMap2 = 関数 (コールバック、thisCtx) {
  if (typeof コールバック !== 'function') {
    `${callback} は関数ではありません` をスローします
  }
  // mapとflatの具体的な実装については、map.jsとflat.jsを参照してください。
  this.map(function (it, i, array) を返す {
    callback.call(thisCtx, it, i, array) を返します。
  }).flat(1)
}

テスト:

arr = [1, 2, 3, 4]とします。


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

エンディング:

これで、JavaScript で 24 以上の配列メソッドを手動で実装する方法に関するこの記事は終了です。JavaScript で 24 以上の配列メソッドを実装する方法の詳細については、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

建国記念日が近づいています。皆様が楽しい休日と楽しい7日間を過ごされることをお祈りいたします。

以下もご興味があるかもしれません:
  • JavaScript配列についてさらに詳しく知るのに役立つ記事
  • Javascript配列の重複排除のいくつかの方法の詳細な説明
  • JavaScript配列の組み込みメソッドの詳細な説明
  • よく使われるJavaScript配列メソッド
  • JavaScript 配列の詳細な概要
  • JavaScriptでよく使われる配列重複排除実戦ソースコード
  • JavaScript で配列の変更を監視する方法
  • JS オブジェクト配列の重複排除のための 3 つの方法の例と比較
  • JSは単純なフィルタリングから複数条件のフィルタリングまで配列フィルタリングを実装します
  • JavaScript 配列の Reduce() メソッドの構文と例の分析

<<:  MySQL ストアド プロシージャ (in、out、inout) の詳細な説明

>>:  生年月日を年齢に変換し、グループ化して人数を数えるMySQLの例

推薦する

vuex で履歴を実装するためのサンプルコード

私は最近、ユーザー操作を元に戻す、またはやり直す機能を備えたビジュアル操作プラットフォームを開発して...

ReactのEffectListの簡単な分析

目次EffectList コレクション最初のレンダリング時のEffectList EffectLis...

JavaScript は setTimeout を使用してカウントダウン効果を実現します

JavaScript ネイティブ コードの記述能力を高め、setTimeout() の使用を強化する...

Node.jsはブレークポイント再開を実装する

目次ソリューション分析スライス履歴書のダウンロード具体的な解決プロセス論理的分析フロントエンドサーバ...

CSSはメッセージパネルをスライドするWebコンポーネント機能を実装します

みなさんこんにちは。私と同じように混乱している方はいらっしゃいませんか。CSS は簡単に始められます...

jsネイティブカルーセルプラグインの制作

この記事では、jsネイティブカルーセルプラグインの具体的なコードを参考までに共有します。具体的な内容...

加算、減算、乗算、除算の機能を実現するには、HTML に 2 つの数値を入力します。

1. parseFloat() 関数Web ページ上に簡単な計算機を作成し、テキスト ボックスに ...

シリアルポート使用時のvue-electronの問題解決

エラーは次のとおりです:キャッチされない TypeError: 未定義のプロパティ 'mod...

Docker での Redis の永続ストレージの詳細な説明

この章では、dockerの下にあるSpring BootプロジェクトでRedisを操作し始めます。準...

HTML ページをスクロールするときに一部のコンテンツを固定位置に固定する方法

この記事では主に、レイアウトに役立つ、HTML ページ内の一部のコンテンツを固定してスクロール時にス...

デザイナーと開発者に役立つ 9 つの超実用的な CSS のヒント

Web デザイナーの頭の中には、仕事に関連する多くの知識が詰まっている必要があります。 CSS は、...

Xtrabackup を使用して MySQL をバックアップおよび復元する方法

目次1. バックアップ1.1 万全の準備1.2 追加の準備2 バックアップとリカバリ2.1 データの...

docker で Apollo をデプロイする詳細なチュートリアル

1. はじめにここでは apollo について詳しく説明しません。公式サイト https://git...

vueの実践的な応用におけるvuexの永続性の詳細な説明

目次vuex 永続性要約するvuex 永続性vuex: ブラウザを更新すると、vuexの状態は初期状...

MySQL 8.0.13 で日付を 0000-00-00 00:00:00 に設定すると発生する問題を解決する

データベース操作を学び始めたばかりです。今日、データを保存していたところ、エラーが発生していることに...