よろしくお願いします!エンジニアのideです。 こちらはアドベントカレンダー23日目の記事になります!
今年は体のあちこちに痛みを感じることが多かったので、来年こそは健康に過ごせる一年になるといいなと願っています。
さて、今回は今年やってきたことを振り返るのもいい機会だなと思い、特に触れる機会が多かったJavaScriptについてまとめてみることにしました。
結果的に基本的な内容が中心となりましたが、改めて理解を深める良いきっかけになったので、これはこれでよしとしています!
それではよろしくお願いいたします!
[目次] ` を使って文字列を囲むことで、${} の中に変数や式を埋め込むことができます。 スプレッド構文は、配列やオブジェクトを展開するために使用します。 分割代入は、配列やオブジェクトの要素を簡単に変数に代入できる構文です。 別名の変数に代入することも可能です。 キー名と変数名が同じ場合、簡潔に書くことができます オブジェクトや配列のプロパティやメソッドにアクセスする際、そのプロパティが存在しない場合でもエラーを発生させず、undefined を返します。 null または undefined の場合にのみ、右辺の値を返します。 falsy(||)チェック 以下のfalsyな値の場合に右辺の値を返します。 空の配列やオブジェクトはtruthyになります。 ディープコピーは、オブジェクトや配列を完全にコピーすることができます。コピー元とコピー先が完全に独立しているので、コピー先の変更を行なってもコピー元に反映されないです。 ディープコピーの方法は、オブジェクトの場合、JSON.parseとJSON.stringifyを使うことで簡単に行うことができます。 ディープコピーの他に、コピー元のデータを一部参照するシャローコピーというものが、あります。 通常のfunctionを使っての関数よりも短く記載することができますが
thisの仕様で異なる部分があります。 1.基本構文 2.引数がない場合、括弧 () を省略せずに記述 3.引数が1個の場合、括弧 () は省略できる 4.function関数とアロー関数の this の違い コールバック関数で this を使う場合、アロー関数の特性が便利 Promise は非同期処理の結果を表現するオブジェクトで、以下の3つの状態をもちます。 Pending 非同期処理が開始され、まだ結果が確定していない状態(進行中の状態)。
サーバーへのリクエストが送信され、レスポンスを待っている状態など Fulfilled(成功) 非同期処理が成功し、結果が得られた状態。 Rejected(失敗) 非同期処理が失敗し、エラーなどの理由で結果が得られなかった状態。
「reject」が呼び出されると、この状態に遷移します。 Promise に基づく非同期処理の結果を扱うメソッドは以下の3つがあります。 then Promiseが「Fulfilled」状態になったときに呼び出されます。
成功時の結果(resolve に渡された値)を受け取るコールバック関数。 catch Promise が「Rejected」状態になったときに呼び出されます。
エラー(reject に渡された値)を受け取るコールバック関数。 finally then や catch の後に呼び出され、成功・失敗に関係なく必ず実行される処理 処理の例です async/awaitはPromise を扱いやすくするためのものです。
awaitはPromiseがresolveされるまで待機します。
resolveが返されると、その値を変数に代入し
もしrejectされる場合、catchにエラーがスローされます。 await は Promise を返す非同期関数や処理に必要です。 forEachが非同期処理をサポートしないため、await を使っても、forEachの実行は非同期処理が完了するのを待ってくれないです。 解決方法として、Promise.allを使用することになります。 Promise.all を使用すると、非同期処理をまとめて実行し、すべての非同期処理が完了まで待つことができます。 改めて振り返ってみるのもいいものですね!
来年はもっと勉強していきたいと思いました! さて明日のアドベントカレンダー担当は、おっくんです! どんな記事を投稿するのか楽しみです!! 最後になりますが、現在弊社ではエンジニアを募集しています! この記事を読んで少しでも興味を持ってくださった方は、ぜひカジュアル面談でお話ししましょう! iimon採用サイト / Wantedly / Green 最後まで読んでいただきありがとうございました!!!
テンプレート文字列
const name = "hoge";
const age = 38;
console.log(`${name}さんの年齢は${age}歳ですね。`);
// hogeさんの年齢は38歳ですね。
スプレッド構文
配列の場合、同じ値が含まれていてもそのまま追加されます。
オブジェクトの場合は、同じキーが存在する場合、後に書かれた値で上書きされます。// 配列
const arr1 = [1, 2, 3];
const arr2 = [3, 4, 5];
const arr = [...arr1, ...arr2];
console.log(arr);
// [1, 2, 3, 3, 4, 5]
// オブジェクト
const obj1 = { name: "tomato", price: 100 };
const obj2 = { name: "orange" };
const obj = {...obj1, ...obj2};
console.log(obj);
// {name: 'orange', price: 100}
分割代入
配列の場合、要素を順番に変数に割り当てる.
オブジェクトの場合、プロパティを変数に割り当てる.// 配列
const fruits = ["apple", "banana", "cherry"];
const [first, second, third] = fruits;
console.log(first); // "apple"
console.log(second); // "banana"
console.log(third); // "cherry"
// オブジェクト
const item = { name: "tomato", price: 100 };
const { name, price } = item;
console.log(name); // tomato
console.log(price); // 100
const item = { name: "tomato", price: 200 };
const { name: itemName, price: salePrice } = item;
console.log(itemName);
// tomato
console.log(salePrice);
// 200
プロパティ名の短縮記法
const name = "tomato";
const price = 100;
const item = { name, price };
console.log(item); // { name: "tomato", price: 100 }
オプショナルチェーン
// 配列
const fruits = ["apple", "ringo"];
console.log(fruits?.[0]); // "apple"
console.log(fruits?.[2]); // undefined
// オブジェクト
const sale = { item: { name: "tomato" } };
console.log(sale.item?.name); // tomato
console.log(sale.cost?.name); // undefined
nullish(??)とfalsy(||)チェック
const value1 = null ?? "hoge";
console.log(value1); // "hoge"
const value2 = undefined ?? "hoge";
console.log(value2); // "hoge"
const value3 = 0 ?? "hoge";
console.log(value3); // 0
const value4 = "" ?? "hoge";
console.log(value4); // ""
const value1 = null || "hoge";
console.log(value1); // "hoge"
const value2 = undefined || "hoge";
console.log(value2); // "hoge"
const value3 = 0 || "hoge";
console.log(value3); // hoge
const value4 = "" || "hoge";
console.log(value4); // hoge
console.log(Boolean([])); // true
console.log(Boolean({})); // true
ディープコピー
const originData = { name: "tomato", price: { salePrice: 100 } };
const deepCopyData = JSON.parse(JSON.stringify(originData));
originData.price.salePrice = 200;
console.log(originData);
// { name: "tomato", price: { salePrice: 200 } };
console.log(deepCopyData);
// { name: "tomato", price: { salePrice: 100 } };
詳しくはコピーマスターの中村さんの記事が分かりやすいので、ぜひご参考に!アロー関数
// function
function add(a, b) {
return a + b;
}
// アロー関数
const add = (a, b) => a + b;
const hello = () => 'こんにちは!';
console.log(hello());
// こんにちは!
const tax = x => x * 1.1;
console.log(parseInt(tax(100)));
// 出力: 110
// function
const obj = {
value: 42,
method: function () {
console.log(this.value); // オブジェクト自身を参照する
},
};
obj.method(); // 出力: 42
// アロー関数
const obj = {
value: 42,
method: () => {
console.log(this.value); // 親スコープの this を参照する
},
};
obj.method(); // 出力: undefined
// function
function Timer() {
this.seconds = 0;
setInterval(function () {
this.seconds++; // エラー: this は undefined
console.log(this.seconds);
}, 1000);
}
new Timer();
// アロー関数
function Timer() {
this.seconds = 0;
setInterval(() => {
this.seconds++; // Timer インスタンスの this を参照
console.log(this.seconds);
}, 1000);
}
new Timer(); // 出力: 1, 2, 3, ...
Promise
「resolve」が呼び出されると、この状態に遷移します。
const promise = new Promise((resolve, reject) => {
const isSuccess = true;
setTimeout(() => {
if (isSuccess) {
resolve('成功!');
} else {
reject('失敗!');
}
}, 1000);
});
promise
.then(result => {
console.log('[成功]状態: Fulfilled', result);
// [成功]状態: Fulfilled 成功!
})
.catch(error => {
console.error('[失敗]状態: Rejected', error);
// [失敗]状態: Rejected 失敗!
})
.finally(() => {
console.log('[終了]');
})
async/await
const fetchData = async () => {
try {
const response = await fetch('https://example.com/user/1');
if (!response.ok) {
throw new Error('ネットワークエラー');
}
const data = await response.json();
console.log('[成功]データ取得:', data);
} catch (error) {
console.error('[失敗]エラー:', error.message);
} finally {
console.log('[終了]データ取得処理完了');
}
};
fetchData();
Promise以外の値を返す関数には awaitは使用しなくて大丈夫です。
以下のようなパターンの場合に必要になります。const fetchData = async () => {
return new Promise(resolve => {
setTimeout(() => resolve('データ取得完了'), 1000);
});
};
const res = await fetchData();
forEachの中でasync/awaitが効かない
const fetchData = async (id) => {
return new Promise((resolve) => {
setTimeout(() => resolve(`完了: ${id}`), 1000);
});
};
const getItems = async (items) => {
items.forEach(async (item) => {
const result = await fetchData(item); // これが効かない
console.log(result);
});
console.log('すべての処理が完了');
};
getItems([1, 2, 3]);
// 最初に「すべての処理が完了しました 」のログが出力されます
const fetchData = async (id) => {
return new Promise((resolve) => {
setTimeout(() => resolve(`完了: ${id}`), 1000);
});
};
const getItems = async (items) => {
const promises = items.map(async (item) => {
const result = await fetchData(item);
console.log(result);
return result;
});
// Promise.all ですべての非同期処理が完了するまで待機
await Promise.all(promises);
console.log('すべての処理が完了');
};
getItems([1, 2, 3]);
// 完了: 1
// 完了: 2
// 完了: 3
// すべての処理が完了
おわりに
参考