はじめに
JavaScriptを書く上で個人的によく使っているなぁと感じる構文を個人的な使用頻度と共にまとめてみました。
使用頻度★★★
モジュールシステム(import/export)
ES2015で追加
他のファイルへ関数やクラスを公開(export)したり、それらを読み込む(import)ことができる機能です。
よく使う使わない以前に前提レベルの機能ですね。
// sampleFunc関数を外部へ公開する
export const sampleFunc = () => {
console.log("this is a function of sample1.js");
}
// sample1.jsからsampleFunc関数をインポート
import { sampleFunc } from "./sample1.js";
// sample1.jsからimportしたsampleFunc関数を実行
sampleFunc();
Node.jsでモジュールを使う場合、以下のどちらかの対応が必要です
・package.jsonにtype: "module"
の記述を追加する
・モジュールとして公開・外部モジュールを使用するファイルの拡張子を.mjs
に変更する
アロー関数
ES2015で追加
() => {}
の形で関数を記述することができます。
アロー関数のthisの挙動はfunction()
でのthisの挙動とは異なるので注意が必要です。
// アロー関数
const arrowFunc = () => {
console.log("arrow function");
}
// 引数が1つなら()を省略可
const arrowFunc2 = name => {
console.log(`Hello! ${name}`);
}
// 1行ならreturnを省略可
const arrowFunc3 = (num) => num * 2;
// 従来の関数
const func = function() {
console.log("function");
}
for of
ES2015で追加
for(const item of array) {}
の形で反復可能オブジェクトから要素を取り出して処理することができます。
const arr = [1, 2, 3, 4, 5];
// for of
for (const item of arr) {
console.log(item);
}
// => 1
// => 2
// => 3
// => 4
// => 5
// ES2015以前の処理
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
テンプレートリテラル
ES2015で追加
${expression}
バッククォート`
で区切られたリテラルで式を埋め込むことができるほか、改行コードなしで複数行の文字列を返せます。
const name = "BAIT0";
// 従来の文字列連結
console.log("Hello " + name + "!!");
// => Hello BAIT0!!
// テンプレートリテラルを用いた連結
console.log(`Hello ${name}!!`);
// => Hello BAIT0!!
// 関数を呼び出して連結
console.log(`Hello ${name.toLowerCase()}!!`);
// => Hello bait0!!
// 改行して出力
console.log(`Hello
${name}!!`);
/** =>
Hello
BAIT0!!
*/
async/await
ES2017で追加
非同期処理をより簡素に扱うことができます。
ES2021まではasync
関数の内部でしかawait
キーワードを使えませんでしたが、
ES2022からはasync関数外部でもawait
を用いた非同期処理を行うことができるようになりました。
// awaitを使った処理
const res = await fetch("https://qiita.com/api/v2/users/BAITO0123/items?page=1");
console.log(await res.json());
// ES2021まで
(async () => {
const res = await fetch("https://qiita.com/api/v2/users/BAITO0123/items?page=1");
console.log(await res.json());
})();
// ES2016まで
fetch("https://qiita.com/api/v2/users/BAITO0123/items?page=1")
.then(res => res.json())
.then(val => {
console.log(val);
});
// ES2015より前
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://qiita.com/api/v2/users/BAITO0123/items?page=1');
xhr.responseType = "json";
xhr.addEventListener('load', function () {
console.log(xhr.response);
});
xhr.send();
使用頻度★★☆
スプレッド構文
ES2015で追加
配列を展開することができます。
ES2017からはオブジェクトもスプレッド構文で展開することができるようになりました。
const arr1 = [10, 20, 30];
// 新しい配列を返す
const arr2 = [...arr1];
// => [10, 20, 30]
// 配列を結合して新しい配列を返す
const arr3 = [...arr1, 40, 50];
// => [10, 20, 30, 40, 50]
/** オブジェクトの場合(ES2017以降) */
const obj1 = { a: "A", b: "B", c: "C" };
// 新しいオブジェクトを返す
const obj2 = {...obj1};
// => {a: 'A', b: 'B', c: 'C'}
// オブジェクトを結合して新しいオブジェクトを返す
const obj3 = {...obj1, d: "D", e: "E", a: "AA"};
// => {a: 'AA', b: 'B', c: 'C', d: 'D', e: 'E'}
個人的にはReactの配列を扱うStateを更新する際によく使うイメージです。
const Sample = () => {
const [ text, setText ] = useState("");
const [ arr, setArr ] = useState([]);
const appendText = () => {
setArr([...arr, text]);
setText("");
}
return (
<>
<input value={text} onChange={(e) => setText(e.target.value)} />
<button onClick={appendText}>追加</button>
{arr.map((val, idx) => <div key={idx}>{val}</div>)}
</>
)
}
分割代入
ES2015で追加
配列、オブジェクトの各プロパティ値をそれぞれ別の変数に代入することができます。
// オブジェクトの分割代入
const obj = { a: "A", b: "B", c: "C" };
const { a, b, ...c } = obj;
// => a = "A"
// => b = "B"
// => c = { c: "C" }
// 配列の分割代入
const arr = [1, 2, 3, 4, 5];
const [x, y, ...z] = arr;
// => x = 1
// => y = 2
// => z = [3, 4, 5]
個人的にはReactコンポーネントのpropsを扱うときに使いがちです。
type Props = {
firstName: string,
lastName: string,
age: number
}
const Person = ({ firstName, lastName, age }: Props) => {
return (
<div>
{`My name is ${firstName} ${lastName}. I'm ${age} years old.`}
</div>
)
}
array.includes
ES2016で追加
引数に渡した要素が配列に含まれるかどうかを返します。
以前でもindexOf()
を使うことで判定できましたが、より直感的に分かりやすくなっています。
const arr = [1, 2, 3, 4, 5];
// includesを使った判定
arr.includes(1);
// => true
// indexOfを用いた判定方法
arr.indexOf(1) > -1;
// => true
Object.entries
ES2017で追加
Objectの各要素を[key, value]
の配列として取得できます。
それをそのままMapコンストラクタに渡すとObjectをMapに変換できます。
const obj = { a: "A", b: "B", c: "C" };
// Object.entries
Object.entries(obj);
// => [ ["a", "A"], ["b", "B"], ["c", "C"] ]
// ObjectをMapに変換
const map = new Map(Object.entries(obj));
// => 0: {"a" => "A"}
// => 1: {"b" => "B"}
// => 2: {"c" => "C"}
// Objectの各要素を反復処理
for(const [key, value] of Object.entries(obj)) {
console.log(`${key}: ${value}`);
}
使用頻度★☆☆
デフォルト引数
ES2015で追加
function(variable = 初期値)
関数の呼び出し時に引数を省略した際のデフォルト値を設定することができます。
// デフォルト引数なしの関数
const greeting = function (name) {
console.log(`hello! ${name}`);
}
// デフォルト引数を指定した関数
const defaultGreeting = function (name = "名無しさん") {
console.log(`hello! ${name}`);
}
greeting();
// => hello! undefined
defaultGreeting();
// => hello! 名無しさん
Set
ES2015で追加
所謂Setで、重複しない値の集合を扱えます。
反復可能オブジェクトなのでfor of
句で扱うことができます。
// Setを作成
const set = new Set();
set.add("A");
set.add("B");
set.add("C");
set.add("A");
// 反復処理
for(const val of set) {
console.log(val);
}
// => A
// => B
// => C
コンストラクタの引数に配列を渡すことで重複排除ができます。
const arr = ["A", "B", "C", "A", "E"];
const set = new Set(arr);
// => Set(4) {'A', 'B', 'C', 'E'}
// Set to Array
const arr2 = [...set]
// => ["A", "B", "C", "E"]
// ワンライナー
const arr3 = [...new Set(arr)];
/** その他の重複排除方法 */
// indexOf + filterを用いた方法
const arr4 = arr.filter((val, idx) => arr.indexOf(val) === idx);
// for文を使った方法
const arr5 = [];
for (const val of arr) {
if (!arr5.includes(val)) {
arr5.push(val);
}
}