Skip to content

安全に使えるユースケース

TypeScriptで安全に使えるユースケースと、その理由を詳しく解説します。

メモリを適切に管理し、不要な参照を削除することで、メモリリークを防ぎます。

// ✅ 良い例: 適切なメモリ管理
class DataManager {
private data: Map<string, any> = new Map();
private maxSize: number;
constructor(maxSize: number = 1000) {
this.maxSize = maxSize;
}
addData(key: string, item: any) {
// サイズ制限を超えた場合、古いデータを削除
if (this.data.size >= this.maxSize) {
const firstKey = this.data.keys().next().value;
this.data.delete(firstKey);
}
this.data.set(key, item);
}
removeData(key: string) {
this.data.delete(key);
}
clear() {
this.data.clear();
}
}
// 使用例
const manager = new DataManager(1000);
manager.addData('key1', { value: 1 });
manager.removeData('key1'); // 明示的に削除
manager.clear(); // すべて削除

なぜ安全か:

  • メモリリークの防止: 不要なデータを明示的に削除
  • サイズ制限: メモリ使用量を制限
  • ガベージコレクション: 参照が削除されると、ガベージコレクションが動作

イベントリスナーの適切な管理

Section titled “イベントリスナーの適切な管理”

イベントリスナーを適切に削除することで、メモリリークを防ぎます。

// ✅ 良い例: イベントリスナーの適切な管理
class ScrollHandler {
private handler: (() => void) | null = null;
setup() {
// 既存のハンドラーを削除
this.cleanup();
// 新しいハンドラーを追加
this.handler = () => {
const element = document.getElementById('target');
if (element) {
element.style.top = window.scrollY + 'px';
}
};
window.addEventListener('scroll', this.handler);
}
cleanup() {
if (this.handler) {
window.removeEventListener('scroll', this.handler);
this.handler = null;
}
}
}

なぜ安全か:

  • メモリリークの防止: イベントリスナーを明示的に削除
  • 参照の削除: ハンドラーの参照を削除することで、ガベージコレクションが動作
  • ライフサイクル管理: オブジェクトのライフサイクルに合わせて管理

仮想スクロールによるDOMノード数の制限

Section titled “仮想スクロールによるDOMノード数の制限”

大量のデータを表示する場合、仮想スクロールを使用してDOMノード数を制限します。

// ✅ 良い例: 仮想スクロールによるDOMノード数の制限
class VirtualList {
private container: HTMLElement;
private items: any[];
private itemHeight: number;
private visibleCount: number;
constructor(
container: HTMLElement,
items: any[],
itemHeight: number = 50,
visibleCount: number = 10
) {
this.container = container;
this.items = items;
this.itemHeight = itemHeight;
this.visibleCount = visibleCount;
this.setup();
}
private setup() {
// コンテナの高さを設定
this.container.style.height = `${this.itemHeight * this.visibleCount}px`;
this.container.style.overflow = 'auto';
// スクロールイベントを設定
this.container.addEventListener('scroll', () => {
this.render();
});
this.render();
}
private render() {
const scrollTop = this.container.scrollTop;
const startIndex = Math.floor(scrollTop / this.itemHeight);
const endIndex = Math.min(
startIndex + this.visibleCount,
this.items.length
);
// 表示範囲のアイテムのみをレンダリング
const visibleItems = this.items.slice(startIndex, endIndex);
// DOMを更新
this.container.innerHTML = '';
visibleItems.forEach((item, index) => {
const element = document.createElement('div');
element.style.height = `${this.itemHeight}px`;
element.textContent = item.text;
this.container.appendChild(element);
});
}
}
// 使用例
const container = document.getElementById('list')!;
const items = Array.from({ length: 10000 }, (_, i) => ({
id: i,
text: `Item ${i}`,
}));
const virtualList = new VirtualList(container, items, 50, 10);
// DOMノード数は常に10個以下に制限される

なぜ安全か:

  • DOMノード数の制限: 表示範囲のアイテムのみをレンダリング
  • パフォーマンスの向上: 大量のデータでもレンダリングパフォーマンスが維持される
  • メモリ使用量の削減: 不要なDOMノードを作成しない

安全に使えるユースケースのポイント:

  • 適切なメモリ管理: 不要な参照を削除し、メモリリークを防止
  • イベントリスナーの適切な管理: イベントリスナーを明示的に削除し、メモリリークを防止
  • 仮想スクロールによるDOMノード数の制限: 大量のデータを表示する場合、仮想スクロールを使用

これらのユースケースを守ることで、安全で信頼性の高いTypeScriptアプリケーションを構築できます。