扩展运算符用来取出对象中所有可遍历属性,拷贝合并到当前对象中(当前对象是一个新的对象集合,和拷贝对象没有必然联系)也就是说这是一个浅拷贝,如果说它具体可以做什么的话,它可以拷贝一个或多个(合并)对象,拷贝一个数组或者多个(合并)数组
对于深浅拷贝,大家第一印象就是深拷贝递归,浅拷贝循环
其实对于深浅拷贝我在之前的博文中提到过了,在这里再多余阐述一下:
let obj = {
a: 10,
b: 20,
c: 30,
d: 40,
e: 66,
f: 88,
};
// 深拷贝
let obj2 = obj;
// 修改obj2
obj2.a = 100;
console.log(obj.a, obj2.a);
// 100 100
不难看出我只是修改了拷贝出来的对象,结果原对象的属性也被我修改了,我们不想这样
这就需要我们探究它是怎么拷贝的,对于引用类型数据来说,拷贝出来的是一个真正的副本,再内存堆栈中它们的地址指向还是同一个,这就导致我们修改obj2的属性之后,修改的其实是对应地址中的数据,因为obj也指向那个地址,这就导致了俩个对象中的属性都被修改了,因为它们指向的是同一个地址呀
那我们的思路是什么?不就是新开创一个地址嘛,再给obj2开创一个新的地址不就可以了吗?
let obj = {
a: 10,
b: 20,
c: 30,
d: 40,
e: 66,
f: 88,
};
// 给到 obj2 一个新的内存地址
let obj2 = {};
for (const key in obj) {
obj2[key] = obj[key];
}
obj2.b = 200;
console.log(obj.b, obj2.b);
// 20 200
解决了,这运用到了浅拷贝的原理
还是上面的例子,我们使用扩展运算符来实现一个浅拷贝
let obj = {
a: 10,
b: 20,
c: 30,
d: 40,
e: 66,
f: 88,
};
let obj2 = { ...obj };
obj2.b = 200;
console.log(obj.b, obj2.b);
// 20 200
如果你是第一次使用扩展运算符,那么你一定会感叹真的是:好用的妈妈给好用开门 - 好用到家了
let obj = {
a: 10,
b: 20,
c: 30,
};
let obj2 = {
d: 40,
e: 66,
f: 88,
};
let obj3 = { ...obj, ...obj2 };
console.log(obj3);
// { a: 10, b: 20, c: 30, d: 40, e: 66, f: 88 }
数组也是类似,我就不做过多阐述了
Object.assign不同于扩展运算符的是:它针对于对象的处理与执行,同样是浅拷贝却比扩展运算符的性能高,常常用来给对象添加属性以及方法
准确来说它用于将所有可枚举属性的值从一个或者多个原对象浅拷贝到目标对象,返回值为目标对象
(如果目标对象中的属性具有相同的键,那么这些冲突属性将会被原对象对应属性所覆盖,如果是多个原对象合并,那么后面的原对象将依次覆盖)
Object.assign( 目标对象 , 原对象1 ,原对象2 ...)
let obj = {
a: 10,
b: 20,
c: 30,
};
let obj2 = {
a: 40,
e: 66,
c: 88,
};
let obj3 = {};
let new_obj = Object.assign(obj3, obj, obj2);
console.log(Object.assign(obj3, obj, obj2));
console.log(new_obj);
// { a: 40, b: 20, c: 88, e: 66 }
// { a: 40, b: 20, c: 88, e: 66 }
重复覆盖,非重复合并
// 基于自动转对象这个我们写一个例子
const stringToObject = Object.assign('Hello_World');
console.log(stringToObject);
console.log(stringToObject[0]);
// [String: 'Hello_World']
// H
undefined
或者 null
,会报错function Test(name, age, hobby) {
Object.assign(this, { name, age, hobby });
}
const test = new Test('Brave-AirPig', 22, '跑步');
console.log(test);
// Test { name: 'Brave-AirPig', age: 22, hobby: '跑步' }
class Test {
constructor(name, age, hobby) {
Object.assign(this, { name, age, hobby });
}
}
const test = new Test('名字', '22', '打代码');
console.log(test);
// Test { name: '名字', age: '22', hobby: '打代码' }
class Test {
constructor(name, age, hobby) {
Object.assign(this, { name, age, hobby });
}
}
const test = new Test('名字', '22', '打代码');
Object.assign(Test.prototype, {
run() {
console.log('跑起来');
},
});
test.run();
// 跑起来
function Test(name, age, hobby) {
Object.assign(this, { name, age, hobby });
}
const test = new Test('Brave-AirPig', 22, '跑步');
Object.assign(Test.prototype, {
run() {
console.log('跑起来');
},
});
test.run();
// 跑起来
如果我们使用ES5的话可以这样写:
class Test {
constructor(name, age, hobby) {
Object.assign(this, { name, age, hobby });
}
}
const test = new Test('名字', '22', '打代码');
Test.prototype.run = () => console.log('跑起来');
test.run();
就是直接往原型上添加方法呗 🤔