最近、JavaScriptの体系的な学習に取り組んでいます。
以前の実務では少し触れた程度でしたが、改めて基礎から学び直す中で気づいた点をまとめます。
目次
- 1.Array.includesと条件判定
- 2.Setによる重複除去
- 3.Mapと辞書型データ構造
- 4.関数型プログラミングによるデータ処理
- 5.関数の合成(compose)
- 6.文字列の反転
- 7.Array.fromを利用した配列生成
- 8.setTimeoutを活用してsetIntervalを代替
- 9.配列の走査時にfor inを避ける
- 10.分割代入(解構賦値)の活用
随時更新中 ...
1.Array.includesと条件判定
通常、条件分岐には || を使います:
function testFruit(fruit) {
if (fruit == 'apple' || fruit == 'orange') {
console.log(`I love it`);
}
}
しかし、比較する値が増える場合、より効率的に記述するにはArray.includesを利用します:
function testFruit(fruit) {
const sweetFruits = ['apple', 'cherry', 'orange', 'banana'];
if (sweetFruits.includes(fruit)) {
console.log(`Sweet fruit`);
}
}
2.Setによる重複除去
Set
は配列に似たデータ構造ですが、要素の重複を許しません。
- 配列の重複除去
const arr = [1, 1, 5, 3, 5, 3, 2];
const unique = [...new Set(arr)];
console.log(unique); // [1, 5, 3, 2]
- Setを配列へ変換して重複除去関数を作成
function unique(array) {
return Array.from(new Set(array));
}
unique([1, 1, 2, 4]);
// 結果: [1, 2, 4]
- 文字列の重複を削除
let str = [...new Set('ababc')].join('');
console.log(str); // 'abc'
- Setを使った和集合・積集合・差集合
let setA = new Set([1,2,3]);
let setB = new Set([4,3,2]);
// 和集合
let union = new Set([...setA, ...setB]);
console.log(union); // set {1,2,3,4}
// 積集合
let intersect = new Set([...setA].filter(x=>{
return setB.has(x);
}));
console.log(intersect); // set {2,3}
// 差集合1
let diff1 = new Set([...setA].filter(x=>{
return !setB.has(x);
}));
console.log(diff1); // set {1}
// 差集合2
let diff2 = new Set([...setB].filter(x=>{
return !setA.has(x);
}));
console.log(diff2); // set {4}
Set
には、集合演算を行うための組み込み関数が既に用意されています。
これらの関数を使用することをお勧めします。詳しくは、以下のMDNドキュメントをご参照ください。
3.Mapと辞書型データ構造
ES6で導入されたMapは、キーと値のペアを保持するデータ構造で、キーには任意の型を指定可能です。
- 基本操作
// 追加
const resultMap = new Map();
resultMap.set('0','1111');
resultMap.set('hoge',['1',2]);
// 取得
resultMap.get('hoge');
// ["1", 2]
// 削除
resultMap.delete('0');
// true
// JSONに変換
resultMap.toJSON();
// [Array(2)]
// 値の更新
resultMap.set('hoge', '1111');
// Map(1) {"hoge" => "1111"}
// サイズ
resultMap.size;
// 1
// クリア
resultMap.clear();
- Mapの反復
Mapのキーや値を順序通りに反復することが可能です:
const map = new Map([["F", "yes"], ["S", "no"]]);
for (let key of map.keys()) {
console.log(key);
}
// 出力: F, S
for (let value of map.values()) {
console.log(value);
}
// 出力: yes, no
4.関数型プログラミングによるデータ処理
- データを変換・フィルタリングする
配列のオブジェクトから年齢が16歳以上の人物を抽出し、構造を変更する例です
let foo = [
{ name: "Stark", age: 21 },
{ name: "Jarvis", age: 20 },
{ name: "Pepper", age: 16 }
];
let results = foo
.filter(person => person.age > 16)
.map(person => ({
person,
friends: []
}));
- 配列の合計を求める
let arr = [1, 2, 3, 5];
let sum = arr.reduce((a, b) => a + b);
// 結果: 11
5.関数の合成(compose)
関数の合成とは、2つの関数を組み合わせて新しい関数を作る仕組みです。
var oldCompose = function(f,g) {
return function(x) {
return f(g(x));
};
};
/* ES6の書き方 */
const compose = (f, g) => x => f(g(x));
// 使用例
const toUpperCase = x => x.toUpperCase();
const exclaim = x => x + '!';
const shout = compose(exclaim, toUpperCase);
console.log(shout("hello"));
// 結果: "HELLO!"
6.文字列の反転
let str = 'hoge';
console.log([...str].reverse().join(''));
// 結果: "egoh"
7.Array.fromを利用した配列生成
Array.from
を用いて、簡単に規則的な配列を作成できます。
let hours = Array.from({ length: 24 }, (_, index) => `${index}時`);
console.log(hours);
// 結果: ["0時", "1時", ..., "23時"]
8.setTimeoutを活用してsetIntervalを代替
setInterval
はタイミングのズレや「フレーム落ち」が起きやすいため、setTimeoutを用いた方が柔軟です。
代わりにsetTimeoutを使用
let doSomething = () => {
// 処理内容
console.log("処理実行");
setTimeout(doSomething, 1000);
};
doSomething();
9.配列の走査時にfor inを避ける
for in
を使うと配列のプロトタイプチェーンも巡回してしまうため、予期しない動作が発生する可能性があります。
let arr = [1, 2];
Array.prototype.test = function() {};
for (let key in arr) {
console.log(arr[key]);
// 結果: 1, 2, ƒ test() {}
}
10.分割代入(destructuring assignment)の活用
- 三層以上のネストには注意
あまりにも深い構造の分割代入は可読性を損ないます。
// 悪い例
let { documentElement: { firstElementChild: { nextSibling }} } = window;
- 一時変数を減らす記述
分割代入は、値の交換などの場面で便利です
// good
[x, y] = [y, x];
// bad
let temp = x;
x = y;
y = temp;