我不知道的深拷贝和浅拷贝

javascript基本数据类型
- 基本数据类型主要是:String,Number,Boolean,Null,Undefined,Symbol
- 基本数据类型存放在栈中
- 基本数据类型值不可变
- 基本类型的比较是值的比较
基本类型的比较是值的比较,只要它们的值相等就认为他们是相等的,例如:
var a = 1;var b = 1;console.log(a === b);//true
复制代码比较的时候最好使用严格等,因为 == 是会进行类型转换的,比如:
var a = 1;var b = true;console.log(a == b);//true
javascript引用类型
- 引用类型存放在堆中
引用类型(object)是存放在堆内存中的,变量实际上是一个存放在栈内存的指针,这个指针指向堆内存中的地址。每个空间大小不一样,要根据情况开进行特定的分配,例如。
var person1 = {name:'nianyuyu'};var person2 = {name:'winter'};
- 引用类型值可变
引用类型是可以直接改变其值的,例如:
var a = [1,2,3];a[1] = 5;console.log(a[1]); // 5
- 引用类型的比较是引用的比较
每次我们对 js 中的引用类型进行操作的时候,都是操作其对象的引用(保存在栈内存中的指针),所以比较两个引用类型,是看其的引用是否指向同一个对象。例如:
var a = [1,2,3];var b = [1,2,3];console.log(a === b); // false
虽然变量 a 和变量 b 都是表示一个内容为 1,2,3 的数组,但是其在内存中的位置不一样,也就是说变量 a 和变量 b 指向的不是同一个对象,所以他们是不相等的。

传值与传址
了解了基本数据类型与引用类型的区别之后,我们就应该能明白传值与传址的区别了。在我们进行赋值操作的时候,基本数据类型的赋值(=)是在内存中新开辟一段栈内存,然后再把再将值赋值到新的栈中。例如:
var a = 10;
var b = a;
a ++ ;
console.log(a); // 11
console.log(b); // 10

所以说,基本类型的赋值的两个变量是两个独立相互不影响的变量。
但是引用类型的赋值是传址。只是改变指针的指向,例如,也就是说引用类型的赋值是对象保存在栈中的地址的赋值,这样的话两个变量就指向同一个对象,因此两者之间操作互相有影响。例如:
var a = {}; // a保存了一个空对象的实例
var b = a; // a和b都指向了这个空对象a.name = 'jozo';
console.log(a.name); // 'jozo'
console.log(b.name); // 'jozo'b.age = 22;
console.log(b.age);// 22
console.log(a.age);// 22
console.log(a == b);// true

浅拷贝
首先深复制和浅复制只针对像 Object, Array 这样的复杂对象的。简单来说,对于字符串类型,浅复制是对值的复制,对于对象来说,浅复制是对对象地址的复制,并没 有开辟新的栈,也就是复制的结果是两个对象指向同一个地址,修改其中一个对象的属性,则另一个对象的属性也会改变
var obj = { a:1, arr: [2,3] };var shallowObj = shallowCopy(obj);function shallowCopy(src) {var dst = {};for (var prop in src) {if (src.hasOwnProperty(prop)) {dst[prop] = src[prop];}}return dst;}
因为浅复制只会将对象的各个属性进行依次复制,并不会进行递归复制,而 JavaScript 存储对象都是存地址的,所以浅复制会导致 obj.arr 和 shallowObj.arr 指向同一块内存地址,导致的结果就是:
shallowObj.arr[1] = 5;
obj.arr[1] // = 5
赋值(=)和浅拷贝的区别
var obj1 = {'name':'zhangsan','age':18,'hobby':['1','2','3']}// 赋值var obj2 = obj1;function shollow(src){var result={};for(var i in src){result[i] = src[i]; }return result;}// 浅拷贝var obj3 = shollow(obj1);obj2.name = "赋值name";console.log(obj1.name); // 赋值nameobj3.name="浅拷贝name"console.log(obj1.name); // 赋值nameobj2.hobby[0] = "赋值name";console.log(obj1.hobby); // ["赋值name", "2", "3"]obj3.hobby[0]="浅拷贝name"console.log(obj1.hobby); // ["浅拷贝name", "2", "3"]
深拷贝
深复制则是开辟新的栈,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。深复制实现代码如下:
- 通过递归解析解决
var obj1 = {'name':'zhangsan','age':18,'hobby':['1','2','3']}// 深拷贝function deepCopy(o,c){var c = c || {};for(var i in o){if(typeof o[i] === 'object') {if(o[i].constructor === Array){c[i] = [];}else{c[i] = {};}deepCopy(o[i],c[i]);}else{c[i] = o[i];}}return c;}var obj2 = deepCopy(obj1,obj2);obj2.hobby[0] = 5;console.log(obj2); //name: "zhangsan" age: 18 hobby: (3) [5, "2", "3"]console.log(obj1);//name: "zhangsan" age: 18 hobby: (3) ["1", "2", "3"]
2. 通过JSON解析解决
var test= {name:{xing:{ first:'张',second:'李'},ming:'老头' },age:20,friend:['nianyuyu','winter']}// JSON.stringify(test) 将 JavaScript 值转换为 JSON 字符串。// JSON.parse() 将字符串转换为 JavaScript 对象:var result = JSON.parse(JSON.stringify(test))result.age = 30result.name.xing.first = '往'result.friend.push('fdagldf;ghad')console.log(test)console.log(result)
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
