JavaScript で知っておきたい最新のテクニック [2021年版]
今やフロントエンド開発で欠かすことができない JavaScript ですが、ES2015以降、ECMAScript が毎年改定されるようになって様々な書き方が可能になってきています。ここではフロントエンジニアが知っておきたい JavaScript のモダンな書き方やテクニックをまとめてみました。
目次
- 1 まとめて変数を定義する
- 2 分割代入する
- 3 オブジェクトからプロパティを削除する
- 4 変数や配列を入れ替える
- 5 配列から重複する要素を除く
- 6 元の配列に変更を加えることなく配列に要素を追加する
- 7 配列をマージする
- 8 オブジェクトのプロパティ名を動的にする
- 9 数字に変換する
- 10 小数点以下を落とす
- 11 小数点第 n 位で四捨五入する
- 12 配列を for ループさせる
- 13 論理AND演算子
- 14 配列をオブジェクトに変換する
- 15 プリミティブの型を取得する
- 16 console を使い分ける
- 17 オブジェクトのプロパティ/メソッドのみをフィルターする
- 18 特定の要素までスクロールする
- 19 node_modules ディレクトリをまとめて削除する
まとめて変数を定義する
let [a, b, c] = [1, 2, 3];
// これは以下と同じです.
let a, b, c;
a = 1;
b = 2;
c = 3;
分割代入する
分割代入ではプロパティ名とは異なる名前の変数に代入することもできます。
const rect = { width: 300, height: 200 };
const { width, height } = rect;
console.log(width); // 300
const { width: w, height: h } = rect;;
console.log(h); // 200
オブジェクトからプロパティを削除する
レスト演算子を利用するとオブジェクトから特定のプロパティを削除することができます。
const person = { firstName: 'Foo', lastName: 'Bar', age: 20 };
const { age: _, ...names } = person;
console.log(names); // { firstName: 'Foo', lastName: 'Bar' }
変数や配列を入れ替える
分割代入を利用すれば、一時変数を利用することなく変数や配列を入れ替えることができます。
let a = 'foo', b = 'bar';
[a, b] = [b, a];
console.log(a); // 'bar'
const arr = [1, 2, 3];
[arr[2], arr[1]] = [arr[1], arr[2]];
console.log(arr); // [1, 3, 2]
配列から重複する要素を除く
一意の値を格納することができる Set
オブジェクトとスプレッド演算子を使うと、配列から重複する要素を取り除くことができます。
const arr = [1, 2, 3, 4, 2, 1, 3, 4, 1, 1];
const uniqueArr = [...new Set(arr)];
console.log(uniqueArr); // [1, 2, 3, 4]
元の配列に変更を加えることなく配列に要素を追加する
スプレッド演算子と配列の slice
メソッドを使えば、元の配列に変更を加えることなく配列に要素を追加することができます。
const insert = (arr, i, value) => [ ...arr.slice(0, i), value, ...arr.slice(i)];
const arr = ['S', 'L', 'C', 'E'];
const result = insert(arr, 2, 'I');
console.log(result); // ['S', 'L', 'I', 'C', 'E']
配列をマージする
const merge = (a, b) => [...a, ...b];
const mergeWithoutDuplications = (a, b) => [...new Set([...a, ...b])];
const a = [1, 2, 3, 4];
const b = [4, 5];
console.log(merge(a, b)); // [1, 2, 3, 4, 4, 5]
console.log(mergeWithoutDuplications(a, b)); // [1, 2, 3, 4, 5]
オブジェクトのプロパティ名を動的にする
const type = 'id';
const item = {
[type]: 'abcd01234';
};
console.log(item); // { id: 'abcd01234' }
console.log(item[type]); // 'abcd01234'
console.log(item['id']); // 'abcd01234'
console.log(item.id); // 'abcd01234'
数字に変換する
+"13" // 13
+true // 1
+false // 0
+null // 0
Number("13") // 13
Number("1.3") // 1.3
Number('foobar') // NaN
parseInt("1234", 10) // 1234
parseInt("1234 numbers", 10) // 1234
parseInt("numbers 1234", 10) // NaN
parseInt("98.76", 10) // 98
parseFloat("12.34") // 12.34
parseFloat("10.00") // 10
小数点以下を落とす
console.log(~~2.3 === 2); // true
console.log(~~(-2.3) === -2); // true
小数点第 n 位で四捨五入する
const round = (value, n) => Math.round(value * 10**n) / 10**n;
console.log(round(1.247, 1)); // 1.2
console.log(round(1.247, 2)); // 1.25
配列を for ループさせる
const animals = ["dog", "cat", "cow"];
for (let fruit of fruits) {
// ...
}
論理AND演算子
condition && myFunc();
// これは以下と同じです.
if (condition) {
myFunc();
}
配列をオブジェクトに変換する
const array = [1, 2, 3];
const object = { ...array };
console.log(object); // { 0: 1, 1: 2, 2: 3 }
プリミティブの型を取得する
const trueTypeOf = (obj) => Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
console.log(trueTypeOf('')); // string
console.log(trueTypeOf(0)); // number
console.log(trueTypeOf()); // undefined
console.log(trueTypeOf(null)); // null
console.log(trueTypeOf({})); // object
console.log(trueTypeOf([])); // array
console.log(trueTypeOf(0)); // number
console.log(trueTypeOf(() => {})); // function
console を使い分ける
console.table
const obj = {
foo: 'bar',
baz: 'qux',
};
console.log(obj); // Bad
console.table(obj); // Good
console.dir(obj); // Good
console.assert
// Bad
if (!isUserLoggedIn) {
console.log("user is not logged in");
}
// Good
console.assert(isUserLoggedIn, "user is not logged in");
オブジェクトのプロパティ/メソッドのみをフィルターする
const store = {
isInitialized: false,
isFetching: false,
fetch() {
// ...
}
};
const properties = Object.getOwnPropertyNames(store).filter(key => typeof store[key] !== "function");
console.log(properties); // ["isInitialized", "isFetching"]
const methods = Object.getOwnPropertyNames(store).filter(key => typeof store[key] === "function");
console.log(methods); // ["fetch"]
上記の方法では直接のメソッドだけを取得することができます。プロトタイプチェインをたどってすべてのメソッドを取得するには、もうひと手間加える必要があります。
const getMethods = (obj) => {
let props = new Set();
let o = obj;
do {
Object.getOwnPropertyNames(o)
.filter(key => typeof obj[key] === 'function')
.forEach(key => props.add(key));
} while (o = Object.getPrototypeOf(o))
return [...props.keys()];
}
console.log(getMethods("")); // ['constructor', 'anchor', 'big', ...]
ここでは Object.getPrototypeOf
でプロトタイプチェインをたどって、メソッドを Set
に追加しています。配列に追加するのではなく Set
に追加しているのは、プロトタイプチェイン上に存在する、同名のメソッドの重複を避けるためです。
特定の要素までスクロールする
特定の要素が見えるようにスクロールするのには、Element
インターフェースの scrollIntoView
メソッドを利用します。
document.querySelector('.hello').scrollIntoView({
behavior: 'smooth'
});
node_modules ディレクトリをまとめて削除する
以下のコマンドでコマンドを実行したディレクトリ以下を探索して node_modules を削除することができます。find . -name "node_modules" ...
のようなコマンドを打つ必要はありません。
npx npkill