赋值,浅拷贝,深拷贝。在我们日常开发中可谓是无处不在,今天简单总结一下。
1.赋值。
在js的基本数据类型中(string, number, boolean, null, undefined, symbol),赋值就是将一个变量的值复制一份在给另一个变量,其中一个只改变,并不影响另一个值。如
let a='123';
let b=a;
b='456'
console.log('a:',a,'b:',b)//a:'123',b:'456'
但是如果是引用类型(对象,数组等)直接写等号赋值是将地址赋值到另一个变量, 其中一个改变,会影响到另一个变量,如
let a=[1,2,3]
let b=a
b[0]=4
console.log(a);//[4,2,3]
如果我们不想原变量受到影响,这个时候我们就会用到深浅拷贝。
2.浅拷贝
那么什么是浅拷贝呢?当我们想要拷贝的数组或对象的内部的值是基本类型时,如[1,2,3]或{name:tom,age:12}。浅拷贝可以拷贝它的值,而且改变拷贝的值,是不会影响原来的值的。如
let a=[1,2,3];
let b=[...a];//用es6的...号可以很容易的实现浅拷贝
b[0]=9;
console.log(a)//1,2,3
console.log(b)//9,2,3
但是如果数组或对象内部还有数组或对象会怎么样了?看下面
let a=[1,2,[1,2,3,6]]
let b=[...a]
b[0]=9;
b[2][1]=8;
console.log(a);//1,2,[1,8,3,6]
console.log(b);//9,2,[1,8,3,6]
一目了然,对内部的基本类型数据更改不会影响原来的值,但是引用类型会影响。这个时候我们会用到深拷贝。
3.深拷贝
无论它的对象或数组嵌套了多少层如 [1,2,[2,1,[1,2]]]类似的,深拷贝都能实现对值的拷贝。改变拷贝值不会影响原来的值。 首先我们先说一下最简单的方法
let obj={
name:'tom'
}
let obj2=JSON.parse(JSON.stringfy(obj))//先把原对象转化为字符串,再转化为对象,这时的对象已经是新的了
但是这样会有局限性,如果对象里面有函数或者promise等复杂的对象,就不行了。
这时我们要手动写,或者引用相关的库( lodash的deepClone方法)(Lodash 简介 | Lodash 中文文档 | Lodash 中文网 (lodashjs.com))。
手动实现如下
//定义检测数据类型的功能函数
function checkedType(target) {
return Object.prototype.toString.call(target).slice(8, -1)
}
//实现深度克隆---对象/数组
function clone(target) {
//判断拷贝的数据类型
//初始化变量result 成为最终克隆的数据
let result, targetType = checkedType(target)
if (targetType === 'Object') {
result = {}
} else if (targetType === 'Array') {
result = []
} else {
return target
}
//遍历目标数据
for (let i in target) {
//获取遍历数据结构的每一项值。
let value = target[i]
//判断目标结构里的每一值是否存在对象/数组
if (checkedType(value) === 'Object' ||
checkedType(value) === 'Array') { //对象/数组里嵌套了对象/数组
//继续遍历获取到value值
result[i] = clone(value)
} else { //获取到value值是基本的数据类型或者是函数。
result[i] = value;
}
}
return result
}
以上就是全部了,大家看的同时,可以在浏览器里面试一下。