最近开发碰到多参数赋值的问题,参数之间总是互相影响,导致出现一些奇怪的bug,查阅了相关资料,全部在这里了,记录一下,希望可以帮到有需要的人
一、= 赋值
let obj1 = {name: '小明', age: 10};
let obj2 = obj1;
obj1.age = 20;
console.log(obj2.age); // 输出20
上述代码中,obj1和obj2指向了同一块内存区域,修改obj1的age属性,也会影响到obj2的age属性。这是因为obj2只是复制了obj1的引用,指向的是同一块内存地址。
二、浅拷贝
浅拷贝是指将一个对象的属性值复制到另一个对象中,如果属性值是引用类型,那么只是复制了它的引用地址,而原对象和新对象的引用指向了同一个地址。这样,在修改新对象中的属性时,原对象相应的属性也会改变。 下面是一个浅拷贝的例子:
const originalObj = {a:1, b:{c:2}};
const newObj = Object.assign({}, originalObj);
newObj.b.c = 3;
console.log(originalObj.b.c); // 输出 3
console.log(newObj.b.c); // 输出 3
在上面的例子中,我们使用了Object.assign方法对原对象进行浅拷贝,并将新对象赋值给了newObj。然后,我们修改了新对象中b属性的c值,结果发现原对象相应的属性也发生了改变。
三、深拷贝
深拷贝是指复制一个对象及其对象的所有子对象的值,并将它们都复制到一个新对象中,这样原对象和新对象没有任何关联,修改新对象中的属性不会影响原对象。 下面是一个深拷贝的例子:
const originalObj = {a:1, b:{c:2}};
const newObj = JSON.parse(JSON.stringify(originalObj));
newObj.b.c = 3;
console.log(originalObj.b.c); // 输出 2
console.log(newObj.b.c); // 输出 3
在上面的例子中,我们使用了JSON的parse和stringify方法对原对象进行深拷贝,并将新对象赋值给了newObj。然后,我们修改了新对象中b属性的c值,结果发现原对象相应的属性没有发生改变。 需要注意的是,深拷贝需要注意循环引用的问题。如果原对象中存在循环引用的情况,深拷贝会陷入死循环,需要我们自己手动处理。
四、ES6展开运算符
展开运算符可以将一个对象中的所有属性展开,并将它们作为新对象的属性,从而实现对象的赋值。 下面是一个展开运算符的例子:
const originalObj = {a:1, b:{c:2}};
const newObj = {...originalObj};
newObj.b.c = 3;
console.log(originalObj.b.c); // 输出 2
console.log(newObj.b.c); // 输出 3
在上面的例子中,我们使用了展开运算符对原对象进行了复制,并将新对象赋值给了newObj。然后,我们修改了新对象中b属性的c值,结果发现原对象相应的属性没有发生改变。 需要注意的是,展开运算符也只能实现浅拷贝,和Object.assign一样,新对象中的引用类型属性只是复制了一个引用地址。
五、结合ES6的解构赋值
结合ES6的解构赋值,我们可以快捷地对一个对象进行赋值。解构赋值可以同时为多个变量赋值,也可以为对象中的某个属性赋值。使用解构赋值,我们可以非常便捷地对一个对象进行复制或者拆分。 下面是一个解构赋值的例子:
const originalObj = {a:1, b:{c:2}};
const { ...newObj } = originalObj;
newObj.b.c = 3;
console.log(originalObj.b.c); // 输出 2
console.log(newObj.b.c); // 输出 3
在上面的例子中,我们使用了解构赋值对原对象进行了复制,并将新对象赋值给了newObj。然后,我们修改了新对象中b属性的c值,结果发现原对象相应的属性没有发生改变。
六、使用Object.getOwnPropertyDescriptors
我们还可以使用Object.getOwnPropertyDescriptors方法来拷贝对象。Object.getOwnPropertyDescriptors方法可以获取对象所有属性的描述符,包括属性方法、可枚举性、可配置性、可写性等等。 下面是一个使用Object.getOwnPropertyDescriptors方法的例子:
const originalObj = {a:1, b:{c:2}};
const newObj = Object.defineProperties({}, Object.getOwnPropertyDescriptors(originalObj));
newObj.b.c = 3;
console.log(originalObj.b.c); // 输出 2
console.log(newObj.b.c); // 输出 3
在上面的例子中,我们使用了Object.getOwnPropertyDescriptors方法和Object.defineProperties方法对原对象进行了复制,并将新对象赋值给了newObj。然后,我们修改了新对象中b属性的c值,结果发现原对象相应的属性没有发生改变。
七、结合函数实现对象的赋值
我们还可以结合函数来实现对象的赋值。函数在实现对象复制时,可以调用Object.assign或者JSON.parse(JSON.stringify())方法实现浅拷贝和深拷贝。 下面是一个结合函数实现对象赋值的例子:
function copyObj(obj, flag){
if(flag){
return JSON.parse(JSON.stringify(obj));
}else{
return Object.assign({}, obj);
}
}
const originalObj = {a:1, b:{c:2}};
const newObj = copyObj(originalObj, true);
newObj.b.c = 3;
console.log(originalObj.b.c); // 输出 2
console.log(newObj.b.c); // 输出 3
在上面的例子中,我们通过编写copyObj函数来实现对象的复制,并将原对象和深拷贝标识传入函数中。然后,我们使用函数来复制原对象,将新对象赋值给了newObj。最后,我们修改了新对象中b属性的c值,结果发现原对象相应的属性没有发生改变。
借鉴于 JS对象赋值给另一个对象_笔记大全_设计学院