JS深复制(拷贝),浅复制(拷贝)与赋值

引言:

学得语言过多而又没消化,所以很多东西是很混乱的,就本题(深复制,浅复制与赋值)的概念来说,所有语言都有(目前接触到的一些语言),但是语言特性原因总有不同吧。本文做个记录。关于JS的深复制,浅复制与赋值。

数据类型与赋值

JS中数据类型分基本类型和引用类型(可以参考其它强类型语言的思维考虑),基本类型赋值时传值,引用类型传引用。

var x=10;
var y=x;
console.log(x,y); // 10 10
y=21;
console.log(x,y); //10 21

//x类型是引用故赋值给y后,x,y同指一片内存空间。
var x={age:10};
var y=x;
console.log(x.age,y.age); // 10 10
y.age=20;
console.log(x.age,y.age); //20 20

浅复制

需求提出:我现在需要把对象x的值赋值给y。意思就是:x,y指向的内存空间不要让他相同。


//ES5写法:
var x={age:10,name:[1,2,3]};
function cloneObj(arg){
  var result={};
  for (var variable in arg) {
    if (arg.hasOwnProperty(variable)) {
      result[variable]=arg[variable];
    }
  }
  return result;
}
var y=cloneObj(x);
console.log(x.age,y.age); // 10 10
y.age=20;
console.log(x.age,y.age); //10 20

//BUT有问题,x的属性中出现了引用类型

y.name.push(0);
console.log(x.name,y.name); //[ 1, 2, 3, 0 ] [ 1, 2, 3, 0 ]

//ES6写法:

var z=Object.assign({},x)
z.name.push(21);
console.log(z.name,x.name); //[ 1, 2, 3, 0, 21 ] [ 1, 2, 3, 0, 21 ]

注:ES6兼容性 --! 好吧,babel解决了 --!

深复制

上面的浅复制出现了一个问题,x的属性中出现了引用类型。这导致y,z中的name属性指向的是同一片地址空间。

所以:console.log(z.name,x.name,y.name); //[ 1, 2, 3, 0, 21 ] [ 1, 2, 3, 0, 21 ] [ 1, 2, 3, 0, 21 ]

所以给出深复制的意义:在复制一个对象时它的属性存在引用类型。

为了解决这个问题:思路(遍历x时,判断每个属性的类型,如果是引用类型的则递归调用)

//ES5写法:
var x={age:10,name:{nn:21}};
function cloneObj(arg){
  var result={};
  for (var variable in arg) {
    if (arg.hasOwnProperty(variable)) {
      if (typeof arg[variable]==='object') {
        result[variable]=cloneObj(arg[variable]);
      }else {
        result[variable]=arg[variable];
      }
    }
  }
  return result;
}
var y=cloneObj(x);
y.name.nn=909;
console.log(x.name.nn,y.name.nn); //21 909


//ES6写法:嗯,就是两个JSON转对象,对象转JSON的API方法
var obj = {a: {b: 1}}
var copy = JSON.parse(JSON.stringify(obj))

obj.a.b = 2
console.log(obj) // {a: {b: 2}}
console.log(copy) // {a: {b: 1}}

注:
1. 深复制我主要是想说ES6的方式;
2. 我把上面的例子中x改了,之前name是个数组,现在是个对象。为什么?

ES6方式深复制的局限性

JS中对象的复制过为麻烦,对象中属性为引用,但是JS里引用也是分很多的啊,例如:Array,function,RegExp…

例如上面ES6深复制方式就不能对function和RegExp类型进行复制,以及JSON.stringify搞不定循环引用的问题。

注:关于深浅复制的问题还有很多每展开讨论,但是感觉实际中用到的也就差不多上述说的一点。

Jquery&&lodash中的深复制

不止是这两个库,还有些库也对深复制进行了实现,具体的实现代码自己找。

lodash中针对不同引用类型(例:array)传参做相应深复制处理。具体参见相应源码。

Jquery中的…..具体略

注:嗯,想做个工具库,就像lodash这种性质的,有兴趣欢迎pr。传送门

(我不是陈X,我也为自己代言。)

总结:

感觉有很多东西(例:鱼腥草|折耳根)吃一口恶心,不消化。多吃几次就好吃了??不,你习惯了。 千里行前莫死于足下!!!

参考:

百度里你能看到的相关文章

注:网络中的博客水平参差不齐,且看且思考!

你可能感兴趣的:(前端集,原生JS)