Home > Article > Web Front-end > Application of Immutable in JavaScript_javascript skills
Mutable object
In JavaScript, objects are reference type data. The advantage is that when objects are frequently modified, they are modified on the basis of the original object and do not need to be recreated. This can effectively utilize memory and will not cause a waste of memory space. Objects This feature can be called Mutable, which literally means "variable" in Chinese.
For Mutable objects, their advantages of being flexible and changeable may sometimes become their disadvantages. The more flexible and changeable the data, the harder it is to control. For an object with a complex structure, it may be modified inadvertently. Without data, if the object is used in multiple scopes, it is difficult to predict whether and when the data will change.
var obj = { /* 一个复杂结构的对象 */ }; doSomething(obj); // 上面的函数之行完后,此时的 obj 还是最初的那个 obj 吗?
To address this problem, the conventional solution is to copy the object into a new object in the form of a deep copy, and then perform modification operations on the new object. This can ensure the controllability of the data, but frequent Copying can cause a lot of waste of memory space.
var obj = { /* 一个复杂结构的对象 */ }; // copy 出一个新的 obj2 // 但是 copy 操作会浪费内存空间 var obj2 = deepClone(obj); doSomething(obj2); // 上面的函数之行完后,无论 obj2 是否变化,obj 肯定还是原来那个 obj
Immutable object
In order to better solve the above problems, the Immutable object appeared. Immutable literally translates into Chinese as "immutable". Every time an Immutable object is modified, a new immutable object is created, and operations on the new object will not affect the data of the original object. This special object is not a new feature of JavaScript, but a set of solutions provided by the industry to solve this problem, and some excellent open source libraries have emerged, the most famous of which is Facebook's Lee Byron open source immutable.js. Of course, Immutable's solution is not original, but comes from Clojure and Scala.
Performance comparison between Mutable and Immutable
The inefficient operations on Mutable objects are mainly reflected in copying and comparison, and Immutable objects solve these two inefficient pain points.
The deep copy operation of an ordinary Mutable object will copy the entire data, but the Immutable object will not copy the entire data when modifying the data, but will transfer the parent-child relationship between the changed node and the unchanged node to On a new node, a structure similar to a linked list. From the perspective of "copy", minimal copying is achieved, and the unchanged parts are shared. Mutable copies "full amount", while Immutable copies "increment", and the usage of memory space is Judgment will be made based on the comparison of the rates.
And based on the feature that a new Immutable object is created every time an Immutable object is modified, the modification status of the data can be saved as a set of snapshots, which is also very convenient.
Let’s talk about comparison operations. For Mutable objects, if you want to compare whether two objects are equal, you must traverse each node of the object for comparison. For objects with complex structures, the efficiency is definitely not much higher. For Immutable objects, immutable.js provides an API to directly determine whether the "values" of two Immutable objects are equal.
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 的作用一样
In actual development applications, performance is not always the most critical and important. For ordinary JavaScript projects, the controllability of data brought by the characteristics of Immutable is more advantageous than performance. , Mutable objects are suitable for use in a small range of closed scopes, while Immutable objects are suitable for use when data needs to be passed across multiple scopes.
The difference in usage between Mutable and Immutable
immutable.js provides a variety of Immutable data structures: including List Stack Map OrderedMap Set OrderedSet Record. These data structures roughly correspond to the native Mutable data structures.
The usage of each data structure will not be explained in detail here. Let’s mainly talk about the difference in usage between Immutable objects and Mutable objects.
Native Mutable objects are very convenient for "reading" and "writing".
var mutableObj = {}; // 写入数据 mutableObj.foo = 'bar'; // 读取数据 console.log(mutableObj.foo);
The Immutable object needs to "read" and "write" data through set and get.
var immutableObj1 = Immutable.Map(); // 写入数据 var immutableObj2 = immutableObj1.set('foo', 'bar'); // 读取数据 console.log(immutableObj2.get('foo')); // => 'bar'
The above example only creates an empty object at the beginning to illustrate the use of the set method. In fact, the initial value can be passed during instantiation.
var immutableObj = Immutable.Map({'foo', 'bar'});
For deep-level data, the access interface provided by immutable.js is very convenient.
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'
If it is a native Mutable object, an object undefined error may be reported when chaining access to a deep-level data. However, the Immutable object will not report an error when encountering this situation and returns undefined.
When debugging, if you want to view the internal structure of an Immutable object, it is recommended to use toJSON() to convert it to an ordinary Mutable object first.