Js direct assignment of objects, shallow copy and deep copy

  After Vue project recently wrote a business, is the need to put in the Data Form dialog box, click after each submission, it is deposited into a el-table form, the form data are required to be submitted multiple times into the form, and then submit this form to submit, to achieve a plurality of form data can also preview, modify a table during other operations. Each form data into the code table codes substantially as follows:

    let object=this.ruleForm;

    this.tableData.push(object);

  Wherein the dialog is used in forms el-form, this.ruleForm vue is an object instance, and this.tableData vue is an array object instance. This.ruleForm directly assigned to a variable object, and then again push into this.tableData in each, it looks logical seems to be nothing wrong, however, this will produce a miraculous phenomenon: each time you fill in a form data when each row of data in the table will be with you a form to fill in is changed.

  Here is a problem that comes to the subject, involving the direct assignment js object, shallow copy and a deep copy.

Direct assignment

  The object is assigned to an object a b b equivalent to a target address pointing to a target address, so they are actually the same object. Since this project is the Vue, the problem appeared in the direct assignment, Vue type of response will make you more intuitive to know their essence. Direct assignment to the example in Figure 1, person object has two properties, one name, one object properties ageAndSex; why should get an object property, this will involve deep and shallow copy copy back problem, this is their sum the difference between. Since the memory address is difficult to monitor, but we can detect both point to the same address by strict equality operator "===."

 If both are the object of FIG. 1, the operator will be strictly equal to check whether they point to the same memory address.

  In the example just an example, as shown in FIG. 2. At the beginning of the assignment to the name attribute personCopy Xiaogang, we found that, person also changed. AgeAndSex object properties to the property assignment personCopy of age 17, person also changed. Namely: direct assignment , modify the properties of non-target object b after assignment, also will affect the original object in a non-object property ; b modify object attribute of the object after the assignment, also will affect the original object a, object properties .

Figure 2 direct assignment

Shallow copy

  Shallow copy will only assign non-object properties Object will not point to the same address. There is a shallow copy ES6 method Object.assign (target, ... sources). Prior to assignment to object directly, for example, as shown in FIG.

FIG 3 shallow copy, the assignment of objects copied object does not point to the same address

  Modify the properties of non-target object b of the assignment does not affect the original object in a non-object property ; b modify object attribute of the object after the assignment, but it will affect the original object is a object attributes , as shown in FIG.

FIG shallow copy 4

  There is also a es6 extended operator "..." shallow copy can be achieved, before or in the object, for example, can be written in this form: var personCopy = {... person}; as shown in FIG.

FIG 5 Extended operator implementation shallow copy (assignment "Xiao Gang" and the like are identical with the results of previous operations, not sticking to out)

   Considering the level of support es6, if your project does not support es6, but want to achieve shallow copy, you can also try concat method js native. However, since only concat operation array, it is necessary to first person as an object array package, written in this form:

    var person=[{name:"小明",ageAndSex:{age:16,sex:"男"}}];

    var personCopy=[].concat(person);

如图6所示,到时想得到person对象的时候var personCopyObjet=pesronCopy[0]即可。

 图6 concat方法实现浅拷贝

深拷贝

  深拷贝会另外拷贝一份一个一模一样的对象,但是不同的是会从堆内存中开辟一个新的区域存放新对象,新对象跟原对象不再共享内存,修改赋值后的对象b不会改到原对象a。即深拷贝,修改赋值后的对象b的非对象属性,不会影响原对象a的非对象属性;修改赋值后的对象b的对象属性,也不会影响原对象a的对象属性。而且,二者不指向同一个对象。

  很明显,深拷贝比较符合我这次的业务需求。深拷贝,比较笨一点的办法就是将自己需要的数据自己封装起来。

      let object={
                           repayment:this.ruleForm.repayment,
                           interestType:this.ruleForm.interestType,
                           productDeadline:this.ruleForm.productDeadline,
                           circumstancesOfDetention:this.ruleForm.circumstancesOfDetention,
                           }
                      this.tableData.push(object);

  但是,这样明显会使代码很臃肿,而且,这还是在需要的数据只有4条的情况下,如果这个object需要封装十几条非对象属性的情况下,明显结构不复杂的情况下,这种代码需要改进。

  有一种非常简单的方法就是序列化成为一个JSON字符串,将对象的内容转换成字符串的形式,再用JSON.parse()反序列化将JSON字符串变成一个新的对象,这样原对象就与复制后的新对象没了必然的关系。以前文提到的personCopy和person为例,写法如下:var personCopy=JSON.parse(JSON.stringify(person));如图7所示。

图7 深拷贝

  但是由于用到了JSON.stringify(),这也会导致一系列的问题,因为要严格遵守JSON序列化规则:原对象中如果含有Date对象,JSON.stringify()会将其变为字符串,之后并不会将其还原为日期对象。或是含有RegExp对象,JSON.stringify()会将其变为空对象,属性中含有NaNInfinity-Infinity,则序列化的结果会变成null,如果属性中有函数,undefined,symbol则经过JSON.stringify()序列化后的JSON字符串中这个键值对会消失,因为不支持。

  所以,这个时候笨的办法也是有好处的,就是面对一些特殊的类型,或是对象属性复杂的情况下,因为自己对程序的需求比较了解,就可以按照自己的需要进行封装。不管黑猫白猫,能抓到老鼠的就是好猫。

Guess you like

Origin www.cnblogs.com/jdWu-d/p/11959800.html