1.数组合并
我们在项目过程中,有时候会遇到需要将两个数组合并成为一个的情况。比如:
const a = [1, 2, 3]
const b = [4, 5, 6]
有两个数组a、b,需求是将两个数组合并成一个。方法如下:
1.1 concat
concat
方法用于多个数组的合并。它将新数组的成员,添加到原数组成员的后部,然后返回一个新数组,原数组不变。
const c = a.concat(b)
console.log(c) // [ 1, 2, 3, 4, 5, 6 ]
console.log(a) // [ 1, 2, 3 ] 不改变本身
contact示例:
['hello'].concat(['world'])
// ["hello", "world"]
['hello'].concat(['world'], ['!'])
// ["hello", "world", "!"]
[].concat({a: 1}, {b: 2})
// [{ a: 1 }, { b: 2 }]
[2].concat({a: 1})
// [2, {a: 1}]
如果数组成员包括对象,concat方法返回当前数组的一个浅拷贝。所谓“浅拷贝”,指的是新数组拷贝的是对象的引用。
var obj = { a: 1 };
var oldArray = [obj];
var newArray = oldArray.concat();
obj.a = 2;
newArray[0].a // 2
1.2 for循环
遍历其中一个数组,把该数组中的所有元素依次添加到另外一个数组中。
for (var i in b) {
a.push(b[i])
}
这样的写法可以解决第一种方案中对内存的浪费,但是会有另一个问题:丑!
1.3 apply或…扩展运算符
push
方法用于在数组的末端添加一个或多个元素,并返回添加新元素后的数组长度。注意,push方法会改变原数组。
- apply
函数的apply方法有一个特性,那就是func.apply(obj,argv)
,argv是一个数组。所以我们可以利用这点,直接上代码:
a.push.apply(a,b);
调用a.push
这个函数实例的apply
方法,同时把,b
当作参数传入,这样a.push
这个方法就会遍历b数组的所有元素,达到合并的效果。
这里可能有点绕,我们可以把b
看成[4,5,6]
,变成这样:
a.push.apply(a,[4,5,6]);
然后上面的操作就等同于:
a.push(4,5,6);
- …扩展运算符
扩展运算符用三个点号(…)表示,功能是把数组或类数组对象展开成一系列用逗号隔开的值。
特殊应用场景:
//数组深拷贝
var arr2 = arr;
var arr3 = [...arr];
console.log(arr === arr2); //true, 说明arr和arr2指向同一个数组
console.log(arr === arr3); //false, 说明arr3和arr指向不同数组
//把一个数组插入另一个数组字面量
var arr4 = [...arr, 4, 5, 6];
console.log(arr4);//[1, 2, 3, 4, 5, 6]
//字符串转数组
var str = 'love';
var arr5 = [...str];
console.log(arr5);//[ 'l', 'o', 'v', 'e' ]
本题解:
a.push(...b)
2.对象合并
2.1 $.extend()(jquery方法)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>对象合并</title>
<script src="https://cdn.staticfile.org/jquery/2.0.0/jquery.min.js"></script>
</head>
<body>
<script>
const obj1 = {a: 1}
const obj2 = {b: 1}
const c = $.extend(obj1, obj2)
console.log(c) // {a: 1, b: 1}
console.log(obj1) // {a: 1, b: 1} obj1已被修改
</script>
</body>
</html>
或者
const obj3 = $.extend({}, obj1, obj2)
console.log(obj3) //{a: 1, b: 1} 不会改变obj1,obj2
2.2 遍历赋值
const obj1 = {a: 1}
const obj2 = {b: 1}
for (var key in obj2) {
if (obj2.hasOwnProperty(key) === true) {
//此处hasOwnProperty是判断自有属性,使用 for in 循环遍历对象的属性时,
// 原型链上的所有属性都将被访问会避免原型对象扩展带来的干扰
obj1[key] = obj2[key]
}
}
console.log(obj1) //{'a':1,'b':2,'c':3};
2.3 Object.assign()
可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。
Object.assign(target, ...sources)
复制一个对象
const obj = {a: 1, b: 2}
const copyObj = Object.assign({}, obj)
console.log(copyObj) // { a: 1,b:2 }
合并多个对象
const obj1 = {a: 1}
const obj2 = {b: 2}
const obj3 = {c: 3}
var obj = Object.assign(obj1, obj2, obj3)
console.log(obj) // { a: 1, b: 2, c: 3 }
console.log(obj1) // { a: 1, b: 2, c: 3 }, 且目标对象自身也会改变。
2.4 对象的深拷贝和浅拷贝
2.4.1 浅拷贝
const obj1 = {a: 1}
const obj2 = {b: {b1: 22, b2: 33}}
Object.assign(obj1, obj2) //obj1拷贝了obj2的属性
console.log(obj1) // {'a':1,'b'{'b1':22,'b2':33}}
console.log(obj1.b.b1) // 22
obj2.b.b1 = 44 //obj2重新赋值
console.log(obj1.b.b1) // 44 obj1.b仅拷贝了对象的指引,所以受原obj2的影响
2.4.2 深拷贝
(1)
const obj1 = {a: 1}
const obj2 = {b: {b1: 22, b2: 33}}
$.extend(true, obj1, obj2) //第一个参数设为true表示深复制
console.log(obj1) // {'a':1,'b'{'b1':22,'b2':33}}
console.log(obj1.b.b1) // 22
obj2.b.b1 = 44 //obj2重新赋值
console.log(obj1.b.b1) // 44 obj1拷贝了obj2的所有属性以及值,并不受obj2的影响
(2)JSON.pase()和JSON.stringfy()结合实现深拷贝