例えば、配列を拡張してrubyのようにfirst
で1件目のエントリーを取得できるようにするにはどうすればよいか、
といったことを紹介します。
const arr = [1, 10, 100, 200]
arr.first // -> 1
拡張する方法を紹介する記事ですので、拡張している内容は特に重要ではありません。
注意
グローバルなものを変更してしまう内容を紹介しています。
一見便利に思えても、名前が衝突する可能性があったりしますので、実用するべきかどうかは慎重に検討してください。
(僕は個人の実装物でしかやりません)
そして、実装する内容も、本当に汎用的に使えるものに絞ったほうがよいです。
Mathオブジェクトに関数を拡張
この場合、単に好きなキー名に関数をアサインしてしまって大丈夫です。
Math.sum = (...numbers) => {
return numbers.reduce((prev, current) => prev + current)
}
Math.sum(1, 10, 100) // -> 111
↑与えられた可変長引数の数値を全て合計して返す関数です。可変長引数やreduce
の解説は省略。
Math.average = (...numbers) => {
return Math.sum(...numbers) / numbers.length
}
Math.average(1, 10, 100) // -> 37
↑与えられた可変長引数の数値の平均を返す関数。さっきのsum
を再利用。
Math.randomInt = (min, max) => {
return Math.floor(Math.random() * (max + 1 - min)) + min
}
Math.randomInt(1, 100) // -> 55
↑第一引数〜第二引数の範囲で、ランダムに整数を返す関数。
Arrayのprototypeにgetter/setterを定義
prototypeを拡張する際は、defineProperty
を使ってください。
Object.defineProperty(Array.prototype, 'first', {
get () {
return this[0]
},
set (value) {
this[0] = value
}
})
const arr = [1, 10, 100, 200]
arr.first // -> 1
arr.first = 5
arr.first // -> 5
配列の1件目にアクセスできるプロパティを実装してみました。
Arrayのprototypeに関数を拡張
同じくdefineProperty
を使い、value
に定義します。
Object.defineProperty(Array.prototype, 'random', {
value () {
return this[Math.randomInt(0, this.length - 1)]
}
})
const arr = [1, 10, 100, 200]
arr.random() // -> 10
arr.random() // -> 200
↑配列内から一つのエントリーをランダムに取得します。さっきのrandomInt
を再利用。
Object.defineProperty(Array.prototype, 'clear', {
value () {
return this.length = 0
}
})
const arr = [1, 10, 100, 200]
arr.clear()
arr // -> []
↑配列を空にする関数です。
(配列はarr.length = 0
で空にできますが、仕様を知っていないと何をしているか意味がわかりません。arr = []
なら分かりやすいけど、別のオブジェクトになってしまうのでやっていることが全然変わってきます。なので明確な名前をつけて関数化しました。)
プリミティブ型のラッパーオブジェクトも拡張
手順は同じです。
Object.defineProperty(Number.prototype, 'half', {
get () {
return this / 2
}
})
const num = 1280
console.log(num) // -> 1280
console.log(num.half) // -> 640
console.log(num.half.half) // -> 320
console.log(num.half.half.half) // -> 160
数値を半分にします。
補足
defineProperty
さきほどのdefinePropertyの第三引数で渡した記述子
には、get
, set
, value
以外にもありますので、詳しくは以下をご覧ください。
Objectのprototype
もちろんMath
やArray
以外でも同じ方法で拡張できますが、Object
のprototypeは変更するとあらゆるものに影響してしまうのでやめたほうが良いです。