あなたが知らないであろう15個の強力なJavaScriptのテクニック🗡🔈🔥
はじめに
この記事はこちらの記事の和訳となります。
なお、著者には許可をいただいております。是非原文もご覧ください。
拙訳なので、ご指摘などあればお待ちしております。
Javascriptのバグ修正や答えを求めてGoogleやStackOverflowを探し回るのは楽しくないでしょう🏴☠️。
この記事では、生産性⚡を最大化し、苦痛🩸を最小化する、20個(訳註:正確には15個)の短く、パワフルなJavaScriptのテクニックを紹介します。
それではコードを見ていきましょう🤘
配列の重複を除去
配列から重複した要素を除去します。
const arr = ["a", "b", "c", "d", "d", "c", "e"]
const uniqueArray = Array.from(new Set(arr));
console.log(uniqueArray); // ['a', 'b', 'c', 'd', 'e']
説明
オブジェクト配列の重複を削除
それぞれが違う値とみなされるので、Set
オブジェクトはオブジェクトの重複を削除できません。JSON.stringify
がここでは役に立ちます。
const arr = [{ key: 'value' }, { key2: 'value2' }, { key: 'value' }, { key3: 'value3' }];
const uniqueObjects = Array.from(
new Set(
arr.map(JSON.stringify)
)
).map(JSON.parse)
console.log(uniqueObjects);
少し長いですが、より効率的な方法はこちらのコメントを参照してください。
説明
訳註参考
index付きの配列のイテレート
.map
や.forEach
のイテレーション関数では、要素のindexを取得できます。
const arr = ['a', 'b', 'c'];
const letterPositions = arr.map(
(char, index) => `${char} is at index ${index}`
)
説明
文字数で文字列を分ける
正規表現の関数.match
を使えば、n
文字で文字を分けることができます。
const str = "asdfghjklmnopq";
const splitPairs = str.match(/.{1,2}/g);
console.log(splitPairs); // ['as', 'df', 'gh', 'jk', 'lm', 'no', 'pq']
説明
ここで使った正規表現/.{1,2}/g
の中で、2という数字が何文字で分けたいかを表しています。あまりがある場合でもこのテクニックは有効です。あるいは、文字数n
が動的に変更されることがある場合、new RegExp
を使うことができます。
const splitPairsBy = (n) => str.match(new RegExp(`.{1,${n}}`, "g"))
文字を異なる文字ごとに分ける
もう一つの正規表現のテクニックとして、match
を使えば、例えば、"aabbc"を配列["aa", "bb", "c"]
に分けることが可能です。
const str = "abbcccdeefghhiijklll";
const splitChars = str.match(/(.)\1*/g);
console.log(splitChars); // ['a', 'bb', 'ccc', 'd', 'ee', 'f', 'g', 'hh', 'ii', 'j', 'k', 'lll']
説明
オブジェクトをイテレートする
Object.entries
はJSONオブジェクトをkey-valueペアの配列に変換し、ループや配列のイテレータで反復処理を可能にしてくれます。
const obj = {
"key1": "value1",
"key2": "value2",
"key3": "value3"
};
const iteratedObject = Object.entries(obj)
.map(([key, value]) => `${key} = ${value}`);
console.log(iteratedObject); // ['key1 = value1', 'key2 = value2', 'key3 = value3']
説明
obj
がObject.entries
に渡された場合、以下のようになります:
[
["key1", "value1"],
["key2", "value2"],
["key3", "value3"]
]
オブジェクトの分割代入と.map
関数を使用すれば、key-valueにアクセスすることができます。
Key-Valueの配列からオブジェクトへの変換
Object.fromEntries
を使えば、オブジェクトのKey-valueペアの配列から、key-valueのオブジェクトへ変換することができます。
const entryified = [
["key1", "value1"],
["key2", "value2"],
["key3", "value3"]
];
const originalObject = Object.fromEntries(entryified);
console.log(originalObject); // { key1: 'value1', ... }
説明
出現頻度をカウントする
配列の中で同じ要素が何個あるのかカウントしたい時があるかもしれません。.filter
関数を使えば、それを達成することができます。
const occurrences = ["a", "b", "c", "c", "d", "a", "a", "e", "f", "e", "f", "g", "f", "f", "f"];
// 同じ文字を一度以上カウントしないようにユニークな配列を作成
const unique = Array.from(new Set(occurrences));
const occurrenceCount = Object.fromEntries(
unique.map(char => {
const occurrenceCount = occurrences.filter(c => c === char).length;
return [char, occurrenceCount]
})
)
console.log(occurrenceCount); // { a: 3, b: 1, c: 2, ... }
ワンライナーの堅牢なコードはこちらのコメントを見てみてください!
説明
replaceコールバック
.replace
関数はただ固定の文字列を置き換えるだけにとどまりません。コールバックを渡して、その中でマッチした文字を使うことができます。
const string = "a dog went to dig and dug a doggone large hole";
const replacedString = string.replace(/d.g/g, str => str + "gy")
console.log(replacedString); // a doggy went to diggy and duggy a doggygone large hole
説明
オプショナルチェーン
JSでundefinedのエラーに遭遇した読者も多いことでしょうが、オプショナルチェーンはそれが発生するのを防いでくれます。
オプショナルチェーン (optional chaining) 演算子 (?.) は、接続されたオブジェクトチェーンの深くに位置するプロパティの値を、チェーン内の各参照が正しいかどうかを明示的に確認せずに読み込むことを可能にします。
const obj = {
"a": "aaaaaaa",
"b": null
};
console.log(obj.b.d); // throws an error
console.log(obj.b?.d); // returns undefined
説明
数字を制約する
たまに、数字をある範囲内に制約させたいと思うかもしれません。そのために、三項演算子を毎回使うのは面倒です。関数を使用すれば、より簡潔になります。
const constrain = (num, min, max) => {
if(num < min) return min;
else if(num > max) return max;
else return num;
}
constrain(5, 1, 3) // 3
constrain(2, 1, 5) // 2
constrain(0, -100, 100) // 0
より良い方法はMath.min
とMath.max
をこのように使う方法でしょう:
const constrain = (num, min, max) => Math.min(Math.max(num, min), max)
@jonrandy に感謝を🙏
説明
配列の前後からインデックスする
.at
関数は、正数、負数を渡すことによって、配列の前後から何番目かの要素を抜き出すことができます。
const arr = [1, 2, 3, 4, 5];
arr.at(0) // 1
arr.at(1) // 2
arr.at(-1) // 5
arr.at(-2) // 4
アルファベット順に並び替える
文字の配列をアルファベット順に並び替えます。
const words = ["javascript", "typescript", "python", "ruby", "swift", "go", "clojure"];
const sorted = words.sort((a, b) => a.localeCompare(b));
console.log(sorted); // ['clojure', 'go', 'javascript', 'python', 'ruby', 'swift', 'typescript']
💡Tip: a.localeCompare(b)
をb.localeCompare(a)
に変えれば、昇順と降順を切り替えられます。
説明
Truthy/Falsyで並び替える
値がtruthyのものを先に、falsyなものを後に持ってくることで、truthy/falsyで配列を並べ替えることができます。
const users = [
{ "name": "john", "subscribed": false },
{ "name": "jane", "subscribed": true },
{ "name": "jean", "subscribed": false },
{ "name": "george", "subscribed": true },
{ "name": "jelly", "subscribed": true },
{ "name": "john", "subscribed": false }
];
const subscribedUsersFirst = users.sort((a, b) => Number(b.subscribed) - Number(a.subscribed))
Number(false)
はゼロ値と同等でNumber(true)
は1と同等です。そのため、sort関数に渡すことができます。
説明
小数をn桁で丸める
.toFixed
を使うと、小数をn
桁で丸めることができます。.toFixed
は数字を文字に置き換えるので、数字に戻す必要があることに注意してください。
console.log(Math.PI); // 3.141592653589793
console.log(Number(Math.PI.toFixed(2)))
説明
ここまで読んでいただいてありがとうございました!
フィードバックお待ちしております。
参考
Discussion
オブジェクト配列の重複を削除
こちらの章に関しては、JSON.stringifyをする前にオブジェクトの中を並び替えないと、以下の2つのようなケースで重複していると判定されないです
JSのdeep equalの検証方法の記事や注釈などの記載があるといいかもしれません
ありがとうございます!注釈追加させていただきました!