ホームページ > ウェブフロントエンド > jsチュートリアル > JavaScript の不変性と参照型を理解する

JavaScript の不変性と参照型を理解する

Linda Hamilton
リリース: 2025-01-06 02:14:39
オリジナル
465 人が閲覧しました

Understanding JavaScript Immutability and Reference Types

不変性と参照型に関する JavaScript の動作は基本的なものですが、よく誤解されています。不変性はデータの安定性を保証しますが、意図しない副作用を回避するには参照型を理解することが重要です。これらの概念を詳細に検討し、その力を効果的に活用するための高度な例とユーティリティ関数を完成させましょう。


JavaScript における不変性

不変性とは、オブジェクトの作成後にその状態を変更できないという概念を指します。 JavaScript では、プリミティブ値 (数値、文字列、ブール値など) は本質的に不変ですが、参照型 (オブジェクト、配列など) はデフォルトで変更可能です。

不変性が重要な理由

  • 予測可能な状態管理
  • デバッグが簡単になりました
  • 関数の副作用を防ぐ

可変データと不変データの例

// Mutable Example
const mutableArray = [1, 2, 3];
mutableArray.push(4); // The original array is modified
console.log(mutableArray); // [1, 2, 3, 4]

// Immutable Example
const immutableArray = [1, 2, 3];
const newArray = [...immutableArray, 4]; // Creates a new array
console.log(immutableArray); // [1, 2, 3]
console.log(newArray);       // [1, 2, 3, 4]
ログイン後にコピー
ログイン後にコピー

参照型とその特徴

参照型 (オブジェクト、配列、関数) は参照としてメモリに保存されます。それらを変数または関数に割り当てたり渡したりしても、その値はコピーされません。参照をコピーします。

:

const obj1 = { name: "Alice" };
const obj2 = obj1;

obj2.name = "Bob";

console.log(obj1.name); // "Bob" - Both variables point to the same reference
ログイン後にコピー

深いコピーと浅いコピー

  • 浅いコピーでは新しいオブジェクトが作成されますが、ネストされたオブジェクトや配列はコピーされません。
  • ディープ コピーは、ネストされた要素を含む構造全体を複製します。

浅いコピーの例:

const obj = { name: "Alice", details: { age: 25 } };
const shallowCopy = { ...obj };

shallowCopy.details.age = 30;
console.log(obj.details.age); // 30 - Nested objects are still linked
ログイン後にコピー

ディープコピーの例:

const deepCopy = JSON.parse(JSON.stringify(obj));
deepCopy.details.age = 35;
console.log(obj.details.age); // 25 - Original object remains unchanged
ログイン後にコピー

不変性と参照の安全性のためのユーティリティ関数

1.ネストされたオブジェクトの不変更新

function updateNestedObject(obj, path, value) {
  return path.reduceRight((acc, key, index) => {
    if (index === path.length - 1) {
      return { ...obj, [key]: value };
    }
    return { ...obj, [key]: acc };
  }, value);
}

// Example
const state = { user: { name: "Alice", age: 25 } };
const newState = updateNestedObject(state, ["user", "age"], 30);
console.log(newState); // { user: { name: "Alice", age: 30 } }
ログイン後にコピー

2.ディープ クローン作成ユーティリティ

function deepClone(obj) {
  return structuredClone ? structuredClone(obj) : JSON.parse(JSON.stringify(obj));
}

// Example
const original = { a: 1, b: { c: 2 } };
const clone = deepClone(original);
clone.b.c = 42;

console.log(original.b.c); // 2 - Original remains unaffected
ログイン後にコピー

3.完全な不変性を実現するためのオブジェクトの凍結

function deepFreeze(obj) {
  Object.freeze(obj);
  Object.keys(obj).forEach((key) => {
    if (typeof obj[key] === "object" && !Object.isFrozen(obj[key])) {
      deepFreeze(obj[key]);
    }
  });
}

// Example
const config = { api: { url: "https://example.com" } };
deepFreeze(config);

config.api.url = "https://changed.com"; // Error in strict mode
console.log(config.api.url); // "https://example.com"
ログイン後にコピー

4.不変配列操作

function immutableInsert(array, index, value) {
  return [...array.slice(0, index), value, ...array.slice(index)];
}

function immutableRemove(array, index) {
  return [...array.slice(0, index), ...array.slice(index + 1)];
}

// Example
const arr = [1, 2, 3, 4];
const newArr = immutableInsert(arr, 2, 99); // [1, 2, 99, 3, 4]
const removedArr = immutableRemove(arr, 1); // [1, 3, 4]
ログイン後にコピー

高度な例

1. Redux スタイルのアーキテクチャで不変状態を管理する

const initialState = { todos: [] };

function reducer(state = initialState, action) {
  switch (action.type) {
    case "ADD_TODO":
      return { ...state, todos: [...state.todos, action.payload] };
    case "REMOVE_TODO":
      return {
        ...state,
        todos: state.todos.filter((_, index) => index !== action.index),
      };
    default:
      return state;
  }
}
ログイン後にコピー

2.非同期関数での参照バグの回避

// Mutable Example
const mutableArray = [1, 2, 3];
mutableArray.push(4); // The original array is modified
console.log(mutableArray); // [1, 2, 3, 4]

// Immutable Example
const immutableArray = [1, 2, 3];
const newArray = [...immutableArray, 4]; // Creates a new array
console.log(immutableArray); // [1, 2, 3]
console.log(newArray);       // [1, 2, 3, 4]
ログイン後にコピー
ログイン後にコピー

不変性と参照処理のベスト プラクティス

  • トップレベルの更新には常に浅いコピーを使用します: スプレッド構文または Object.assign を使用します。
  • ディープ クローン作成にはライブラリを優先します: Lodash (cloneDeep) のようなライブラリは、堅牢なソリューションを提供します。
  • 共有可変状態を最小限に抑える: 明確な所有権構造なしで関数間でオブジェクトを受け渡すことを避けます。
  • 状態管理における不変性の活用: Redux や Immer などのツールにより、不変状態の更新が直感的に行えます。
  • 読み取り専用構成には Object.freeze を使用します: 定数が変更されていないことを確認してください。

結論

不変性と参照型を理解することは、堅牢で保守可能な JavaScript アプリケーションを作成するために不可欠です。ユーティリティ関数を活用し、ベスト プラクティスに従うことで、バグを防止し、状態管理を簡素化し、シームレスに拡張するコードを作成できます。

以上がJavaScript の不変性と参照型を理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート