TypeScriptのベストプラクティスを見てみようの第8弾です。
36. コールバックよりもPromiseを優先する
Promiseは非同期処理を扱うためのオブジェクトで、コールバックに比べてコードが読みやすく、エラー処理も簡単です。特にasync/awaitと組み合わせることで、非同期処理が直感的に書けるようになります。
サンプルコード
// コールバックの例 function fetchData(callback) { setTimeout(() => { callback(null, "データを取得しました"); }, 1000); } fetchData((err, data) => { if (err) { console.error(err); } else { console.log(data); } }); // Promiseの例 function fetchData() { return new Promise((resolve, reject) => { setTimeout(() => { resolve("データを取得しました"); }, 1000); }); } fetchData().then(data => { console.log(data); }).catch(err => { console.error(err); }); // async/awaitの例 async function fetchData() { return new Promise((resolve, reject) => { setTimeout(() => { resolve("データを取得しました"); }, 1000); }); } async function getData() { try { const data = await fetchData(); console.log(data); } catch (err) { console.error(err); } } getData();
あまりコールバック自体を使うケースがないので、今後もasync/awaitを使っていく所存です。Promiseを使うことで、コードが読みやすくなり、非同期処理が簡単になります。JavaScriptの非同期処理を効率的に行うために、引き続きPromiseを活用していきたいです。
37. 奇妙なJavaScriptの機能を使わない
JavaScriptには多くの機能がありますが、使うべきでないものも存在します。例えば、配列のlengthプロパティの更新、withキーワード、voidキーワード、ネイティブオブジェクトのプロトタイプ更新、eval()関数などです。これらはコードの可読性や保守性を損なう原因となります。
サンプルコード
// 配列のlengthプロパティの更新 let arr = [1, 2, 3, 4]; arr.length = 2; // [1, 2] // withキーワード with (Math) { let x = cos(3.14); console.log(x); } // voidキーワード void function() { console.log("これは無視されます"); }(); // ネイティブオブジェクトのプロトタイプ更新 Array.prototype.customMethod = function() { return this.length; }; // eval()関数 let x = 10; eval('x = 20'); console.log(x); // 20
lengthを更新するケースもないですし、withは使いません。ただ、voidは関数の戻り値の型を定義する際に使ったりはしていたので、推奨されないんだと思いました。これらの奇妙な機能は、コードの可読性や保守性を損なう可能性があるため、今後は使用を控えるようにします。
38. ウェブブラウザの気まぐれに屈しない
特定のブラウザに特化したコードを書くことは避けるべきです。これにより、コードの保守が難しくなり、他のブラウザでの動作保証ができなくなります。標準に基づいたコードを書くことで、幅広いブラウザでの互換性を保つことができます。
サンプルコード
// 特定のブラウザに特化したコード(避けるべき) if (navigator.userAgent.indexOf('MSIE') !== -1) { // Internet Explorer特有の処理 } // 標準に基づいたコード const element = document.querySelector('#example'); element.textContent = '標準に基づいたテキストの設定';
特定のブラウザ特化したコードが何なのか不明ですが、今はChromeやSafariのシェアが高いと思うのでそれらをカバーできていれば良さそうに思えます。ただし、標準に基づいたコードを書くことは、将来的な保守性を考えると非常に重要です。ブラウザのシェアは変動することが多いため、標準に従ったコードを意識していきたいです。
39. スクリプトはページの一番下に配置する
スクリプトをページの一番下に配置することで、ページの読み込み速度を向上させることができます。ブラウザはスクリプトの読み込み中に他の処理を中断するため、スクリプトを最後に読み込むことで、ユーザーはページの他の部分を早く見ることができます。
サンプルコード
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ページタイトル</title> </head> <body> <h1>コンテンツ</h1> <p>このページにはスクリプトがあります。</p> <script src="script.js"></script> <!-- スクリプトはここに配置 --> </body> </html>
直接HTMLファイルにJavaScriptを記述することはないですが、感覚的にスクリプトは下に配置するイメージを持っていました。ページの読み込み速度を向上させるために、非同期に読み込むスクリプトも含めて、適切に配置することが重要です。これにより、ユーザー体験が向上します。
40. DOMアクセスを最小限に抑える
DOMアクセスはブラウザのパフォーマンスに大きな影響を与えるため、できるだけ最小限に抑えるべきです。Reactなどのフレームワークを使うと、仮想DOMを通じて効率的にDOM操作が行えますが、直接DOMを操作する場合は注意が必要です。
サンプルコード
// 非効率的なDOM操作 const list = document.getElementById('list'); for (let i = 0; i < 100; i++) { const item = document.createElement('li'); item.textContent = `アイテム ${i}`; list.appendChild(item); } // 効率的なDOM操作 const list = document.getElementById('list'); const fragment = document.createDocumentFragment(); for (let i = 0; i < 100; i++) { const item = document.createElement('li'); item.textContent = `アイテム ${i}`; fragment.appendChild(item); } list.appendChild(fragment);
高頻度で使うReactでは仮想DOMを使用しているため、あまり直接DOMを操作する場面はないですが、jQueryを使う場合は気をつけていきたいです。DOM操作はパフォーマンスに影響を与えるため、できるだけ最小限に抑えるようにします。効率的なDOM操作を意識することで、アプリケーションのパフォーマンスが向上します。