やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

配列の最後の要素を取得する5つの方法

 どの方法もリスクがあり最適解がない。

標準API

const A = ['最初', '中間', '最後']
const methods = [
//  (a)=>a.pop(),        // 配列内容を変更してしまう破壊メソッド!
    (a)=>a[a.length-1],  // 
    (a)=>a.slice(-1)[0], // 
    (a)=>a.at(-1),       // ES2022 Chrome 92
]
for (let m of methods) { console.log(m(A), m) }
方法 残念点
a.pop() 配列内容を変更してしまう破壊メソッド
a[a.length-1] 冗長かつ判りにくい
a.slice(-1)[0] 冗長かつ判りにくい
a.at(-1) ES2022(Chrome 92以降で使用可)
  1. a.at(-1)が最も判りやすいが、古いブラウザで動作しない
  2. a.slice(-1)[0]はほぼ全環境で実行可能
  3. a[a.length-1]aの参照が二回あるため同変数名が繰り返され冗長
  4. a.pop()は破壊メソッドのため参照には不適切

 実行可能性を優先すると2のa.slice(-1)[0]を使うことになる。いずれ1のa.at(-1)か、もっと良いAPIに置き換わる日が来るはず。だが、それまではa.slice(-1)[0]という可読性の低いAPIを使わざるを得ない。

 できれば以下のように参照したかったが、標準APIにはない。OTZ

a.last
a[-1]

自作API

 ないなら作ればいい。

 名前汚染してもいいなら、次のように定義できる。

array-last.js

Object.defineProperty(Array.prototype, 'last', {
    get: function() { return this[this.length-1] }
});

 Arraylastゲッターを定義した。次のように呼び出す。

A.last

 できた。最高!

 あとはこれをarray-last.jsなどの名前を付けてファイルに保存しHTMLで読み込めば使い回せる。次のように。

<script src="array-last.js"></script>
<script>
window.addEventListener('DOMContentLoaded', async(event) => {
  const A = ['最初', '中間', '最後']
  console.log(A.last) // 最後
})
</script>

問題

  • 将来の拡張により名前重複しバグる可能性あり(標準API、他ライブラリ)
  • 毎回<script src="array-last.js"></script>で読み込むの面倒

 グローバル汚染、prototype汚染は、一般的に危険であり非推奨。もし標準APIに同名のそれが実装されたとき、微妙な挙動の違いなどでバグが起きかねない。他のライブラリで似たようなことをして名前が重複したとき、読み込んだ順によってどれが実行されるか決まってしまい、微妙な挙動の違いなどでバグが起きかねない。

ポリフィルはダメ絶対

 ポリフィルat()を実装するのも手だ。誰かに最適なコードを作ってもらい、自分はそれをCDNでお手軽に利用する。最高である。

 と思っていたらマルウェアが仕込まれて事件になっていた。OTZ

 もう他人の書いたコードなんて信じない💢

結論

 最後の要素を取得する最適解はない。

 選べ。次の中から犠牲にすべきものを。

コード 長所 短所
a.slice(-1)[0] どの環境でも動作する 可読性が低い
a.at(-1) 標準API。可読性が高い ES2022(Chrome 92以降で使用可)
a.last 可読性が高い prototype汚染。<script>読込必要

 公式さん早くlastAPI作って。[-1]もね。(合わせてfirstも頼む)