Javascript中數組的合併和對象的合併、拷貝

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 深拷貝
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的影響
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章