这是我参与8月更文挑战的第11天,活动详情查看:8月更文挑战;
前言
了解浅拷贝之前,需要储备的知识点
-
js数据类型分类有两种:
-
基本数据类型:Boolean、Null、Undefined、Number、String、Symbol,这些也可以称作
原始值。原始值存放在栈中,不可以被改变。 -
引用数据类型:Object、Array、Function、RegExp、Date,这些可以称为
引用值。引用值存在堆里。栈内存会提供一个引用的地址指向堆内存里的值
-
-
深拷贝与浅拷贝的概念只存在于引用数据类型。
正文
含义
浅拷贝:简单理解,浅拷贝对于基本类型而言,相当于开辟了一块新的空间;对于引用类型而言,就是只拷贝了对象的第一层属性。
类型是引用数据类型的话,浅拷贝复制的是内存中的地址,如果其中一个对象改变了这个内存中的地址,肯定会影响到另一个对象。
常用方法
-
- 使用方法:Object.assign(target, ...sources)
let target = { a: "A", b: "B" }; let source = { b: "b", c: "c"}; const returnedTarget = Object.assign(target, source); console.log(target); // {a: "A", b: "b", c: "c"} console.log(returnedTarget); // {a: "A", b: "b", c: "c"}如果目标对象
(target)中的属性具有相同的键,则属性将被源对象(sources)中的属性覆盖。后面的源对象的属性将类似地覆盖前面的源对象的属性。Object.assign方法只会拷贝源对象(sources)自身的并且可枚举的属性到目标对象(target)。String类型和 Symbol 类型的属性都会被拷贝。
-
- 使用方法:let objClone = { ...obj };
let arr = [1, 2, 3]; let arr2 = [...arr]; arr2.push(4); console.log(arr2); // [1,2,3,4] console.log(arr); // [1,2,3]展开语法和
Object.assign()行为一致, 执行的都是浅拷贝(只遍历一层)。 如果属性都是基本类型的值,使用扩展运算符进行浅拷贝会更加方便。 -
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 a = [ 2, 4, 6, { x: 0 } ];
var b = Array.prototype.slice.call(a);
b[0] = 8;
console.log(a); // [ 2, 4, 6, { x: 0 }];
console.log(b); // [ 8, 4, 6, { x: 0 }];
// 从输出结果可以看出,浅拷贝后,数组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 } ];
// 从输出结果可以看出,浅拷贝后,数组中对象的属性会根据修改而改变
// 说明浅拷贝的时候拷贝的已存在对象的对象的属性引用。
注意:后边这两个适用于基本类型值的数组
手动实现一个浅拷贝
- 基本思路
- 对基础类型做一个最基本的一个拷贝;
- 对引用类型开辟一个新的存储,并且拷贝一层对象属性。
- 代码实现如下
这样就实现了一个浅拷贝,小伙伴们可以好好理解一下实现浅拷贝的代码和思路,然后研究一下深拷贝,后边文章我们会继续讲解一下深拷贝。const shallowClone = (target) => { // 首先进行判断,是不是object,且不为null,不满足返回传入的target,满足则继续。 if (typeof target === 'object' && target !== null) { // 继续判断 target是不是一个数组,是的话创建一个空数组,不是的话创建一个空对象。 const cloneTarget = Array.isArray(target) ? []: {}; // 依次遍历target中的每一项,把对应属性赋值给目标对象的属性,满足返回cloneTarget for (let prop in target) { if (target.hasOwnProperty(prop)) { cloneTarget[prop] = target[prop]; } } return cloneTarget; } else { return target; } }
总结
前端漫漫长途,我们都在路上,希望可以和小伙伴们一起交流,一起进步。持续更新ing.....