深拷贝与浅拷贝。

159 阅读3分钟

大家好,我是小逗号,初次来到这里,多多关照,希望我这次作品对于大家认识了解拷贝有一定的帮助。

今天我们一起来了解深拷贝与浅拷贝。

  • 在我我们的JS分为两大类型:
  1. 基本类型:我们常见的数字,字符串,布尔等都属于基本数据类型,这些数据类型大小保存在栈当中。

  2. 引用类型:我们常见的数组,对象都属于引用数据类型,保存在堆内存当中,而堆内存则是储存地址。

  • 首先我们来理解深拷贝与浅拷贝的概念:
  1. 浅拷贝:只复制引用,会进行彼此影响。
  2. 深拷贝:完全拷贝出来一个新的对象,开辟新的空间。修改拷贝对象源对象不会受到影响。

我们来看一下日常业务中拷贝的方法

浅拷贝的方法

  1. 赋值的方法 “=“ 我们这种的拷贝类型拷贝拷贝基本类型的时候是深拷贝,当我们拷贝引用的时候就变成了浅拷贝
var arr1 = ["刘备", "张飞", "关羽"];
var arr2 = arr1;
arr2.push("赵云");
console.log(arr1); // ["刘备", "张飞", "关羽", "赵云"]
console.log(arr2); // ["刘备", "张飞", "关羽", "赵云"]

浅层深拷贝的方法

  1. 赋值的方法 “=“
var a = "张飞";
var b = a;
a = "关羽";
console.log(a); // 关羽
console.log(b); // 张飞
  1. Es6当中的扩展运算符拷贝方法

[...]
var arr = ["诸葛亮", "鲁肃", "司马懿"]
let arr1 = [...arr]
arr.push("曹操")
console.log(arr); // ["诸葛亮", "鲁肃", "司马懿", "曹操"]
console.log(arr1); //  ["诸葛亮", "鲁肃", "司马懿"]
{...} 
let obj = { name: "张飞" }
let obj2 = {...obj }
obj.age = 18;
console.log(obj); // {name: 'Corey', age: 18}
console.log(obj2); // {name: 'Corey'}
  1. 利用数组对象的方法进行拷贝
Array.slice()
var arr = ["诸葛亮", "鲁肃", "司马懿"]
let arr1 = arr.slice()
arr.push("曹操")
console.log(arr); // ["诸葛亮", "鲁肃", "司马懿", "曹操"]
console.log(arr1); // ["诸葛亮", "鲁肃", "司马懿"]
Array.concat()
var arr = ["诸葛亮", "鲁肃", "司马懿"]
let arr1 = arr.concat()
arr.push("曹操")
console.log(arr); // ["诸葛亮", "鲁肃", "司马懿", "曹操"]
console.log(arr1); //  ["诸葛亮", "鲁肃", "司马懿"]
Array.from()
var arr = ["诸葛亮", "鲁肃", "司马懿"]
let arr1 = Array.from(arr, item => item)
arr.push("曹操")
console.log(arr); // ["诸葛亮", "鲁肃", "司马懿", "曹操"]
console.log(arr1); //  ["诸葛亮", "鲁肃", "司马懿"]
Object.assign()
let obj = {name: "张飞"}
let obj2 = {}
Object.assign(obj2, obj);
// let obj2 = Object.assign({}, obj); 
obj.age = 18;
console.log(obj); // {name: 'Corey', age: 18}
console.log(obj2); // {name: 'Corey'}

通过以上的方法我们得出结论,以上都是浅拷贝。 以下我们来看一下深拷贝。

深层深拷贝的方法

  1. 使用JSON.parse(JSON.stringify())进行深拷贝
var arr = [{id: "1",name: "张三" }, [1, 2, 3, 4, 5], function(x) { console.log(x);} ]
let arr1 = JSON.parse(JSON.stringify(arr));
arr1.push("曹操")
console.log(arr); // [{…}, Array(5), null] 
console.log(arr1); //[{…}, Array(5), ƒ, "曹操"]
// 很明显没有因为arr1的改变而影响arr,是深拷贝
// 现在我们来调用里面的方法试一试
arr1[2](10) // Uncaught TypeError: arr1[2] is not a functionat demo4.html: 155
// JSON.parse(JSON.stringify()) 这种方法只能拷贝80%,是不能拷贝方法的
  1. 递归拷贝
var arr = [{id: "1",name: "张三" }, [1, 2, 3, 4, 5], function(x) {console.log(x);}]    
// 手写递归函数
function Clone(obj) {
const tar = obj.constructor === Array ? [] : {}
for (let keys in obj) {
if (obj.hasOwnProperty(keys)) {
if (obj[keys] && typeof obj[keys] === "object") {
tar[keys] = obj[keys].constructor === Array ? [] : {}
tar[keys] = Clone(obj[keys])
} else {
tar[keys] = obj[keys]
}
}
}
return tar
}
const Arr = Clone(arr)
Arr[2](10) // 10
// 返回了一个10这种手写递归拷贝是可取的哦

通过这两个方法我们得出以下结论:

  1. JSON.parse(JSON.stringify())可以进行深拷贝,但是不会拷贝里面的方法。
  2. 递归方法进行开辟新的存储地址这种拷贝,可以拷贝里面的方法。

如果这次的作品给大家带来了帮助,就来个关注,以后还会有更多关于前端的作品哦