どの方法もリスクがあり最適解がない。
標準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以降で使用可) |
a.at(-1)
が最も判りやすいが、古いブラウザで動作しないa.slice(-1)[0]
はほぼ全環境で実行可能a[a.length-1]
はa
の参照が二回あるため同変数名が繰り返され冗長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(){returnthis[this.length-1]}});
Array
にlast
ゲッターを定義した。次のように呼び出す。
A.last
できた。最高!
あとはこれをarray-last.js
などの名前を付けてファイルに保存しHTMLで読み込めば使い回せる。次のように。
<scriptsrc="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> 読込必要 |
公式さん早くlast
API作って。[-1]
もね。(合わせてfirst
も頼む)