ホームページ > 記事 > ウェブフロントエンド > JavaScript における Immutable の適用_javascript スキル
可変オブジェクト
JavaScript では、オブジェクトは参照型データであるため、オブジェクトが頻繁に変更される場合、元のオブジェクトに基づいて変更されるため、再作成する必要がなく、メモリを効率的に利用でき、メモリの無駄が発生しないという利点があります。オブジェクト この機能は、中国語で文字通り「変数」を意味する Mutable と呼ぶことができます。
Mutable オブジェクトの場合、データが柔軟で変更可能であるほど、制御が難しくなり、データがなければどこかで誤って変更される可能性があります。オブジェクトが複数のスコープで使用されている場合、データが変更されるかどうか、いつ変更されるかを予測するのは困難です。
var obj = { /* 一个复杂结构的对象 */ }; doSomething(obj); // 上面的函数之行完后,此时的 obj 还是最初的那个 obj 吗?
この問題に対処するための従来の解決策は、オブジェクトをディープ コピーの形式で新しいオブジェクトにコピーし、その後、新しいオブジェクトに対して変更操作を実行することです。これにより、データの制御性が確保されますが、コピーが頻繁に行われます。メモリ空間を大量に浪費する可能性があります。
var obj = { /* 一个复杂结构的对象 */ }; // copy 出一个新的 obj2 // 但是 copy 操作会浪费内存空间 var obj2 = deepClone(obj); doSomething(obj2); // 上面的函数之行完后,无论 obj2 是否变化,obj 肯定还是原来那个 obj
不変オブジェクト
上記の問題をより適切に解決するために、Immutable オブジェクトが登場しました。Immutable は中国語に直訳すると「不変」です。不変オブジェクトが変更されるたびに、新しい不変オブジェクトが作成され、新しいオブジェクトに対する操作は元のオブジェクトのデータに影響を与えません。この特別なオブジェクトは JavaScript の新しい機能ではなく、この問題を解決するために業界によって提供された一連のソリューションであり、いくつかの優れたオープンソース ライブラリが登場しており、その中で最も有名なものは Facebook の Lee Byron オープンソースimmutable です。 js。もちろん、Immutable のソリューションはオリジナルではなく、Clojure と Scala から来ています。
Mutable と Immutable のパフォーマンスの比較
Mutable オブジェクトに対する非効率な操作は主にコピーと比較に反映されており、Immutable オブジェクトはこれら 2 つの非効率な問題点を解決します。
通常の Mutable オブジェクトのディープ コピー操作ではデータ全体がコピーされますが、Immutable オブジェクトはデータを変更するときにデータ全体をコピーせず、変更されたノードと変更されていないノードの間の親子関係を新しいノードに転送します。ノード。リンクされたリストに似た構造。 「コピー」という観点から見ると、最小限のコピーが実現され、変更されていない部分は「全額」コピーされ、Immutable は「増分」コピーされます。メモリ空間の使用量の比較に基づいて判断されます。料金。
また、Immutable オブジェクトが変更されるたびに新しい Immutable オブジェクトが作成される機能を利用して、データの変更状況をスナップショットとして保存できるため、これも非常に便利です。
比較演算について話しましょう。 Mutable オブジェクトの場合、2 つのオブジェクトが等しいかどうかを比較する場合は、オブジェクトの各ノードを走査して比較する必要がありますが、複雑な構造を持つオブジェクトの場合、効率はそれほど高くありません。 Immutable オブジェクトの場合、immutable.js は 2 つの Immutable オブジェクトの「値」が等しいかどうかを直接判断する API を提供します。
var map1 = Immutable.Map({a:1, b:1, c:1}); var map2 = Immutable.Map({a:1, b:1, c:1}); assert(map1 !== map2); // 不同的 Immutable 实例,此时比较的是引用地址 assert(Immutable.is(map1, map2)); // map1 和 map2 的值相等,比较的是值 assert(map1.equals(map2)); // 与 Immutable.is 的作用一样
実際の開発アプリケーションでは、パフォーマンスが常に最も重要であるわけではありません。通常の JavaScript プロジェクトでは、パフォーマンスよりも Immutable の特性によるデータの制御性の方が有利であり、Mutable オブジェクトは狭い範囲での使用に適しています。一方、Immutable オブジェクトは、複数のスコープ間でデータを渡す必要がある場合の使用に適しています。
Mutable と Immutable の使用法の違い
immutable.js は、List Stack Map OrderedMap Set OrderedSet Record などのさまざまな Immutable データ構造を提供します。これらのデータ構造は、ネイティブの Mutable データ構造にほぼ対応します。
ここでは、各データ構造の使用法については詳しく説明しません。主に、Immutable オブジェクトと Mutable オブジェクトの使用法の違いについて説明します。
Native Mutable オブジェクトは、「読み取り」と「書き込み」に非常に便利です。
var mutableObj = {}; // 写入数据 mutableObj.foo = 'bar'; // 读取数据 console.log(mutableObj.foo);
Immutable オブジェクトは、set と get を通じてデータの「読み取り」と「書き込み」を行う必要があります。
var immutableObj1 = Immutable.Map(); // 写入数据 var immutableObj2 = immutableObj1.set('foo', 'bar'); // 读取数据 console.log(immutableObj2.get('foo')); // => 'bar'
上記の例では、set メソッドの使用法を示すために最初に空のオブジェクトを作成しているだけです。実際には、インスタンス化中に初期値を渡すことができます。
var immutableObj = Immutable.Map({'foo', 'bar'});
深いレベルのデータの場合、immutable.js が提供するアクセス インターフェイスは非常に便利です。
var immutableObj1 = Immutable.fromJS({ a: { b: 'c' }, d: [1, 2, 3] }); // 读取深层级的数据 console.log(immutableObj1.getIn(['a', 'b'])); // => 'c' console.log(immutableObj1.getIn(['d', 1])); // => 2 // 修改深层级的数据 var immutableObj2 = immutableObj1.setIn(['a', 'b'], 'd'); console.log(immutableObj2.getIn(['a', 'b'])); // => 'd'
ネイティブの Mutable オブジェクトの場合、深いレベルのデータへのアクセスをチェーンするときにオブジェクトの未定義エラーが報告されることがありますが、Immutable オブジェクトはこの状況が発生してもエラーを報告せず、未定義を返します。
デバッグ時に Immutable オブジェクトの内部構造を表示したい場合は、最初に toJSON() を使用して通常の Mutable オブジェクトに変換することをお勧めします。