赋值,浅拷贝,深拷贝
和原数据是否指向同一对象 | 第一层数据为基本数据类型 | 原数据中包含子对象 | |
---|---|---|---|
赋值 | 是 | 会使原数据一起改变 | 会使原数据一起改变 |
浅拷贝 | 否 | 不会使原数据一起改变 | 会使原数据一起改变 |
深拷贝 | 否 | 不会使原数据一起改变 | 不会使原数据一起改变 |
赋值:赋值是将某一数值或对象赋给某个变量的过程
1、基本数据类型
2、引用数据类型
浅拷贝:创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝
1.如果属性是基本数据类型,拷贝的就是基本类型的值
2.如果属性是引用数据类型,拷贝的就是内存地址
所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
浅拷贝具体例子:
Object.assign()
方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
Array.prototype.slice()
不会改变原数组,slice()
方法返回一个新的数组对象,这一对象是一个由 begin
和 end
(不包括end
)决定的原数组的浅拷贝。
深拷贝:深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存
当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。拷贝前后两个对象互不影响。
深拷贝具体例子:
JSON.parse(JSON.stringify(object))
jQuery.extend()
和 lodash.cloneDeep()
其中(1)(2)(3) undefined
、symbol
和函数这三种情况,会直接忽略。
// saucxs
let obj = {
name: 'saucxs',
a: undefined,
b: Symbol('saucxs'),
c: function() {}
}
console.log(obj);
// {
// name: "saucxs",
// a: undefined,
// b: Symbol(saucxs),
// c: ƒ ()
// }
let b = JSON.parse(JSON.stringify(obj));
console.log(b);
// {name: "saucxs"}
其中(4)循环引用会报错
// saucxs
let obj = {
a: 1,
b: {
c: 2,
d: 3
}
}
obj.a = obj.b;
obj.b.c = obj.a;
let b = JSON.parse(JSON.stringify(obj));
// Uncaught TypeError: Converting circular structure to JSON
其中(5)* new Date
情况下,转换结果不正确。
// saucxs
new Date();
// Mon Dec 24 2018 10:59:14 GMT+0800 (China Standard Time)
JSON.stringify(new Date());
// ""2018-12-24T02:59:25.776Z""
JSON.parse(JSON.stringify(new Date()));
// "2018-12-24T02:59:41.523Z"
解决方法转成字符串或者时间戳就好了。
// saucxs
let date = (new Date()).valueOf();
// 1545620645915
JSON.stringify(date);
// "1545620673267"
JSON.parse(JSON.stringify(date));
// 1545620658688
其中(6)正则情况下
// saucxs
let obj = {
name: "saucxs",
a: /'123'/
}
console.log(obj);
// {name: "saucxs", a: /'123'/}
let b = JSON.parse(JSON.stringify(obj));
console.log(b);
// {name: "saucxs", a: {}}