1.利用assign合并多个对象,第一个参数为目标对象,后面可以有多个源对象。
- 首先我们需要知道的是assign实行的是浅拷贝,也就是说如果源对象的某个属性值是对象,那么assign拷贝的是它的引用。
- assign是将源对象的可枚举属性复制到目标对象,如果属性名相同后面的属性会覆盖前面属性,只有一个参数assign会直接返回该参数。
- 如果参数不是对象,assign会先将其转为对象,再进行操作
- assign可以处理数组,但数组会被视为对象
let obj1 = {
name: 'dk',
age: '99',
feature: 'stronge'
}
let obj2 = {
name: 'tk',
age: '99',
feature1: 'noStronge',
address: {
city: '广州',
address: {
city: '深圳'
}
},
skills: ['JavaScript', 'React', 'Node']
}
let res = Object.assign(obj1, obj2);
res.address.address.city = '广州';
console.log(obj2);
console.log(res);
2.利用扩展运算符
需要注意的是利用扩展运算符...合并对象 同样是进行浅拷贝
let obj1 = {
name: 'dk',
age: '99',
feature: 'stronge'
}
let obj2 = {
name: 'tk',
age: '99',
feature1: 'noStronge',
address: {
city: '广州',
address: {
city: '深圳'
}
},
skills: ['JavaScript', 'React', 'Node']
}
let res = {...obj1, ...obj2};
res.address.address.city = '杭州';
console.log(obj2);
console.log(res);
3.手写函数(浅拷贝实现)
let merger = (...opts) => {
let res = {};
let combine = (opt) => {
for(let prop in opt) {
if(opt.hasOwnProperty(prop)) {
res[prop] = opt[prop];
}
}
}
//扩张运算符将两个对象合并到一个数组里,因此opts可以调用length方法
for (let i = 0; i < opts.length; i++) {
combine(opts[i]);
}
return res;
}
let obj1 = {
name: 'dk',
age: '99',
feature: 'stronge'
}
let obj2 = {
name: 'tk',
age: '99',
feature1: 'noStronge',
address: {
city: '广州',
address: {
city: '深圳'
}
},
skills: ['JavaScript', 'React', 'Node']
}
let res = merger(obj1, obj2);
//查看是否是浅拷贝
res.address.address.city = '杭州';
console.log(res);
console.log(obj2);
上面实现的函数主要的知识点有
Object对象的hasOwnProperty方法,主要用于判断实例对象是否有该属性。
for in循环主要用于遍历对象属性。不管是自身的还是继承的属性。
- 既然说到for in,顺便提一下for of 与for in的区别
- 先说结论,for in 一般用于遍历对象属性,for of 一般用于遍历数组。
- 官方文档给的解释是for in 用于循环一个可枚举对象,for of用于可迭代对象,可枚举对象和可迭代对象之间的关系就是:可枚举对象视为矩形,可迭代对象视为正方形。因此,所有可迭代对象都是可枚举对象,但并非所有可枚举都是可迭代对象。它们之间的关系就和矩形和正方形之间差不多。
- 用object来说的话,for in遍历的是key,for of 遍历的是value,但是js中的object用for of会直接报错。
4.手写函数(实现深拷贝)
下面实现深拷贝的函数思路和浅拷贝差不多,就是多出了一个递归,如果有不了解递归的小伙伴,可以去了解一下。
let merger = (...opts) => {
let res = {};
let combine = (opt) => {
for(let prop in opt) {
if(opt.hasOwnProperty(prop)) {
//下面是深拷贝与浅拷贝的区别,用到了递归的思想
if(Object.prototype.toString.call(opt[prop]) === '[object Object]') {
res[prop] = merger(res[prop], opt[prop]);
}else {
res[prop] = opt[prop];
}
}
}
}
//扩张运算符将两个对象合并到一个数组里因此可以调用length方法
for (let i = 0; i < opts.length; i++) {
combine(opts[i]);
}
return res;
}
let obj1 = {
name: 'dk',
age: '99',
feature: 'stronge'
}
let obj2 = {
name: 'tk',
age: '99',
feature1: 'noStronge',
address: {
city: '广州',
address: {
city: '深圳'
}
},
skills: ['JavaScript', 'React', 'Node']
}
let res = merger(obj1, obj2);
//查看是否是浅拷贝
res.address.address.city = '杭州';
console.log(obj2);
console.log(res);
上面代码的知识点有
- Object.prototype.toString.call() 用于判断类型,他其实是toString( )方法和call( )方法结合使用,toString( ) 方法用于返回对象类型字符串,而call( )方法就是绑定this嘛。
- 上面在merger中调用merger就是递归的思想,有兴趣的小伙伴可以去学学递归的思想。
5.最后介绍最后一种办法Lodash's中的merge( )方法。Lodash's是node中的库。它也是一种深拷贝的办法。
const _ = require('lodash');
let obj1 = {
name: 'dk',
age: '99',
feature: 'stronge'
}
let obj2 = {
name: 'tk',
age: '99',
feature1: 'noStronge',
address: {
city: '广州',
address: {
city: '深圳'
}
},
skills: ['JavaScript', 'React', 'Node']
}
const res = _.merge(obj1, obj2);
console.log(res);