js什么是深拷贝和浅拷贝?JS的赋值与深浅拷贝实例

人气:431 ℃/2024-03-07 13:46:42

JS的赋值与深浅拷贝实例

赋值

//基本数据类型赋值var a = 10;var b = a;a ;console.log(a); // 11console.log(b); // 10//引用数据类型赋值let a = { name: '11' }let b = ab.name = '22'console.log(a.name) // 22console.log(b.name) // 22

浅拷贝

注意:浅拷贝只复制一层对象的属性

实现浅拷贝方法

方法一:Object.assign

*语法:Object.assign(target, ...sources) *

ES6中拷贝对象的方法,接受的第一个参数target是拷贝后的对象,剩下的参数是要拷贝的对象sources(可以是多个)

例1:

let target = {};let source = {a:'11',b:{name:'duoduo'}};Object.assign(target ,source);console.log(target); // { a: '11', b: { name: 'duoduo' } }

例2:

let target = {};let source = {a:'11',b:{name:'duoduo'}};Object.assign(target ,source);source.a = '22';source.b.name = 'nana'console.log(source); // { a: '22', b: { name: 'nana' } }console.log(target); // { a: '11', b: { name: 'nana' } }

Object.assign注意事项

  1. 只拷贝源对象的自身属性(不拷贝继承属性)
  2. 它不会拷贝对象不可枚举的属性
  3. undefined和null无法转成对象,它们不能作为Object.assign参数,但是可以作为源对象
  4. 属性名为Symbol 值的属性,可以被Object.assign拷贝。

方法二:Array.prototype.slice

实现原数组的浅拷贝

var a = [ 1, 3, 5, { x: 1 } ];var b = Array.prototype.slice.call(a);b[0] = 2;console.log(a); // [ 1, 3, 5, { x: 1 } ];console.log(b); // [ 2, 3, 5, { x: 1 } ];// 从输出结果可以看出,浅拷贝后,数组a[0]并不会随着b[0]改变而改变// 说明a和b在栈内存中引用地址并不相同。

var a = [ 1, 3, 5, { x: 1 } ];var b = Array.prototype.slice.call(a);b[3].x = 2;console.log(a); // [ 1, 3, 5, { x: 2 } ];console.log(b); // [ 1, 3, 5, { x: 2 } ];// 从输出结果可以看出,浅拷贝后,数组中对象的属性会根据修改而改变// 说明浅拷贝的时候拷贝的已存在对象的对象的属性引用。

方法三:Array.prototype.concat

let array = [{a: 1}, {b: 2}];let array1 = [{c: 3},{d: 4}];let array2=array.concat(array1);array1[0].c=123;console.log(array2);// [ { a: 1 }, { b: 2 }, { c: 123 }, { d: 4 } ]console.log(array1);// [ { c: 123 }, { d: 4 } ]

方法四:...扩展运算符

语法:var cloneObj = { ...obj };

var a = [ 1, 3, 5, { x: 1 } ];var b = {...a};b[0] = 2;console.log(a); // [ 1, 3, 5, { x: 1 } ];console.log(b); // [ 2, 3, 5, { x: 1 } ];// 从输出结果可以看出,浅拷贝后,数组a[0]并不会随着b[0]改变而改变// 说明a和b在栈内存中引用地址并不相同。

var a = [ 1, 3, 5, { x: 1 } ];var b = {...a};b[3].x = 2;console.log(a); // [ 1, 3, 5, { x: 2 } ];console.log(b); // [ 1, 3, 5, { x: 2 } ];// 从输出结果可以看出,浅拷贝后,数组中对象的属性会根据修改而改变// 说明浅拷贝的时候拷贝的已存在对象的对象的属性引用。

其他方法:

//浅拷贝实现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;}shallowObj.arr[1] = 5;obj.arr[1] // = 5

深拷贝

深拷贝开辟一个新的栈,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性

注意:深拷贝对对象中的子对象进行递归拷贝,拷贝前后两个对象互不影响

实现方法:

方法一:JSON.parse(JSON.stringify())

let arr = [1, 2, {name: ' duoduo'}];let newarr = JSON.parse(JSON.stringify(arr));newarr[2].name = 'nana'; console.log(newarr); // [ 1, 2, { username: 'nana' } ]console.log(arr); // [ 1, 2, { username: 'duoduo' } ]

JSON.stringify()实现深拷贝注意点

  1. 拷贝的对象的值中如果有函数,undefined,symbol则经过JSON.stringify()序列化后的JSON字符串中这个键值对会消失
  2. 无法拷贝不可枚举的属性,无法拷贝对象的原型链
  3. 拷贝Date引用类型会变成字符串
  4. 拷贝RegExp引用类型会变成空对象
  5. 对象中含有NaN、Infinity和-Infinity,则序列化的结果会变成null
  6. 无法拷贝对象的循环应用(即obj[key] = obj)

方法二:jquery 的 $.extend

var $ = require('jquery');var obj1 = { a: 1, b: { f: { g: 1 } }, c: [1, 2, 3]};var obj2 = $.extend(true, {}, obj1);

赋值、深拷贝、浅拷贝

浅拷贝和**拷贝区别

浅拷贝只复制一层对象的属性,而深拷贝则递归复制了所有层级

百科

More+
首页/电脑版/网名
© 2025 NiBaKu.Com All Rights Reserved.