襄阳网站建设公司,做网站切片,新品发布会方案,注重网站内容维护文章首发于sau交流学习社区 一、赋值#xff08;Copy#xff09; 赋值是将某一数值或对象赋给某个变量的过程#xff0c;分为#xff1a; 1、基本数据类型#xff1a;赋值#xff0c;赋值之后两个变量互不影响 2、引用数据类型#xff1a;赋**址**#xff0c;两个变量具… 文章首发于sau交流学习社区 一、赋值Copy 赋值是将某一数值或对象赋给某个变量的过程分为 1、基本数据类型赋值赋值之后两个变量互不影响 2、引用数据类型赋**址**两个变量具有相同的引用指向同一个对象相互之间有影响 对基本类型进行赋值操作两个变量互不影响。 // saucxs
let a saucxs;
let b a;
console.log(b); // saucxsa change;
console.log(a); // changeconsole.log(b); // saucxs对引用类型进行赋**址**操作两个变量指向同一个对象改变变量 a 之后会影响变量 b哪怕改变的只是对象 a 中的基本类型数据。 // saucxs
let a {name: saucxs,book: {title: You Dont Know JS,price: 45}
}
let b a;
console.log(b);
// {
// name: saucxs,
// book: {title: You Dont Know JS, price: 45}
// } a.name change;
a.book.price 55;
console.log(a);
// {
// name: change,
// book: {title: You Dont Know JS, price: 55}
// } console.log(b);
// {
// name: change,
// book: {title: You Dont Know JS, price: 55}
// } 通常在开发中并不希望改变变量 a 之后会影响到变量 b这时就需要用到浅拷贝和深拷贝。 二、浅拷贝Shallow Copy 1、什么是浅拷贝 创建一个新对象这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型拷贝的就是基本类型的值如果属性是引用类型拷贝的就是内存地址 所以如果其中一个对象改变了这个地址就会影响到另一个对象。 上图中SourceObject 是原对象其中包含基本类型属性 field1 和引用类型属性 refObj。浅拷贝之后基本类型数据 field2 和 filed1 是不同属性互不影响。但引用类型 refObj 仍然是同一个改变之后会对另一个对象产生影响。 简单来说可以理解为浅拷贝只解决了第一层的问题拷贝第一层的**基本类型值**以及第一层的**引用类型地址**。 2、浅拷贝使用场景 2.1 Object.assign() Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。 有些文章说Object.assign() 是深拷贝其实这是不正确的。 // saucxs
let a {name: saucxs,book: {title: You Dont Know JS,price: 45}
}
let b Object.assign({}, a);
console.log(b);
// {
// name: saucxs,
// book: {title: You Dont Know JS, price: 45}
// } a.name change;
a.book.price 55;
console.log(a);
// {
// name: change,
// book: {title: You Dont Know JS, price: 55}
// } console.log(b);
// {
// name: saucxs,
// book: {title: You Dont Know JS, price: 55}
// } 上面代码改变对象 a 之后对象 b 的基本属性保持不变。但是当改变对象 a 中的对象 book 时对象 b 相应的位置也发生了变化。 2.2 展开语法 Spread // saucxs
let a {name: saucxs,book: {title: You Dont Know JS,price: 45}
}
let b {...a};
console.log(b);
// {
// name: saucxs,
// book: {title: You Dont Know JS, price: 45}
// } a.name change;
a.book.price 55;
console.log(a);
// {
// name: change,
// book: {title: You Dont Know JS, price: 55}
// } console.log(b);
// {
// name: saucxs,
// book: {title: You Dont Know JS, price: 55}
// } 2.3 Array.prototype.slice方法 slice不会改变原数组slice() 方法返回一个新的数组对象这一对象是一个由 begin和 end不包括end决定的原数组的**浅拷贝**。 // saucxs
let a [0, 1, [2, 3]];
let b a.slice(1);
console.log(b);
// [1, [2, 3]]a[1] 99;
a[2][0] 4;
console.log(a);
// [0, 99, [4, 3]]console.log(b);
// [1, [4, 3]] 可以看出改变 a[1] 之后 b[0] 的值并没有发生变化但改变 a[2][0] 之后相应的 b[1][0] 的值也发生变化。 说明 slice() 方法是浅拷贝相应的还有concat等在工作中面对复杂数组结构要额外注意。 三、深拷贝Deep Copy 3.1 什么是深拷贝 深拷贝会拷贝所有的属性并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。拷贝前后两个对象互不影响。 3.2 使用深拷贝的场景 3.2.1 JSON.parse(JSON.stringify(object)) // saucxs
let a {name: saucxs,book: {title: You Dont Know JS,price: 45}
}
let b JSON.parse(JSON.stringify(a));
console.log(b);
// {
// name: saucxs,
// book: {title: You Dont Know JS, price: 45}
// } a.name change;
a.book.price 55;
console.log(a);
// {
// name: change,
// book: {title: You Dont Know JS, price: 55}
// } console.log(b);
// {
// name: saucxs,
// book: {title: You Dont Know JS, price: 45}
// } 完全改变变量 a 之后对 b 没有任何影响这就是深拷贝的魔力。 我们看下对数组深拷贝效果如何。 // saucxs
let a [0, 1, [2, 3]];
let b JSON.parse(JSON.stringify( a.slice(1) ));
console.log(b);
// [1, [2, 3]]a[1] 99;
a[2][0] 4;
console.log(a);
// [0, 99, [4, 3]]console.log(b);
// [1, [2, 3]] 对数组深拷贝之后改变原数组不会影响到拷贝之后的数组。 但是该方法有以下几个问题 1会忽略 undefined 2会忽略 symbol 3不能序列化函数 4不能解决循环引用的对象 5不能正确处理new Date() 6不能处理正则 其中123 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 GMT0800 (China Standard Time)JSON.stringify(new Date());
// 2018-12-24T02:59:25.776ZJSON.parse(JSON.stringify(new Date()));
// 2018-12-24T02:59:41.523Z 解决方法转成字符串或者时间戳就好了。 // saucxs
let date (new Date()).valueOf();
// 1545620645915JSON.stringify(date);
// 1545620673267JSON.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: {}} PS为什么会存在这些问题可以学习一下 JSON。 除了上面介绍的深拷贝方法 常用的还有jQuery.extend() 和 lodash.cloneDeep()后面文章会详细介绍源码实现。 四、总结 和原数据是否指向同一对象 第一层数据为基本数据类型 原数据中包含子对象 赋值是 改变会使原数据一起改变 改变会使原数据一起改变 浅拷贝否 改变不会使原数据一起改变 改变会使原数据一起改变 深拷贝否 改变不会使原数据一起改变 改变不会使原数据一起改变 五、参考 1、深拷贝和浅拷贝 2、MDN之Object.assign() 3、MDN之展开语法 4、MDN之Array.stypetype.slice()转载于:https://www.cnblogs.com/chengxs/p/10788442.html