你不知道的簡單陣列拷貝方法全解

筱筱醬發表於2019-03-04

在我們的日常工作中,經常會遇到一些把一個值賦給另一個值,簡單資料型別我們可以直接用=的方式進行簡單值拷貝,那麼遇到陣列或者物件這些引用型別的拷貝應該怎麼做呢?接下來簡單總結了一些陣列的淺拷貝和深拷貝的方法

淺拷貝【Shallow copy】

concat()

concat()方法主要用於陣列的連線,該方法不會改變現有的陣列,而僅僅會返回被連線陣列的一個副本。

var arr1 = [1,2,3,4];
var arr10 = arr1.concat([]);
console.log(arr1); //1,2,3,4
console.log(arr10); //1,2,3,4
arr10.push(10);
console.log(arr10); //1,2,3,4,10
console.log(arr1); //1,2,3,4
//從此方法可以看出,使用concat方法實現了陣列的淺拷貝,當操作arr10時沒有影響到arr1陣列的資料

複製程式碼
slice()

slice()方法用於陣列的切割,基本的語法是slice(start,end);start指定從原始陣列的那個位置開始切割,end表示到那個位置結束【省略該引數預設結束位置是陣列的最後一個原始】,我們可以使用slice()方法不指定任何引數實現陣列的淺拷貝

var arr1 = [1,2,3];
var arr2 = arr1.slice();
console.log(arr1); //1,2,3
console.log(arr2); //1,2,3
arr2.push(4);
console.log(arr1); //1,2,3
console.log(arr2); // 1,2,3,4
//隻影響了arr2陣列,實現了陣列的淺拷貝
複製程式碼
…【ES6擴充套件運算子】

對ES6熟悉的人肯定都知道這個方法,…是ES6的新語法,它可以用於陣列的擴充套件,

var arr1 = [1,2,3]
var arr2 = [...arr1];
console.log(arr1); //1,2,3
console.log(arr2); //1,2,3
arr2.push(4);
console.log(arr1); //1,2,3
console.log(arr2); // 1,2,3,4
//隻影響了arr2陣列,實現了陣列的淺拷貝

複製程式碼

以上是小編簡單總結的陣列的淺拷貝方法,同樣你也可以用自己編寫的方式進行陣列淺拷貝

//實現淺拷貝
function shallowCopy( target ){
 if(typeof target !== `object`) return ;
 //判斷目標型別,來建立返回值
 var newObj = target instanceof Array ? [] : {};
 
 for(var item in target){
  //只複製元素自身的屬性,不復制原型鏈上的
  if(target.hasOwnProperty(item)){
   newObj[item] = target[item]
  }
 }
 
 return newObj
}
var test = [10,3,{name:`zs`,age:10}]
var cloneTet = shallowCopy(test);
cloneTest[2].name = `lisi`;
console.log(test[2].name) //lisi
console.log(cloneTest[2].name) // lisi
//。
複製程式碼

從上面的結果可以看出,在修改拷貝出來的cloneTest時,原始的test值也被修改了。為了實現不被修改,我們需要使用到深拷貝

深拷貝

巧用JSON.parse(JSON.stringify(Obj))

同樣我們可以先將陣列轉為物件字串然後在轉為物件的方式進行淺拷貝

var arr1 = [1,2,3];
var arr2 = JSON.parse(JSON.stringify(arr1));
console.log(arr1); //1,2,3
console.log(arr2); //1,2,3
arr2.push(4);
console.log(arr1); //1,2,3
console.log(arr2); // 1,2,3,4
//隻影響了arr2陣列,實現了陣列的淺拷貝
複製程式碼
使用遞迴的方式實現深拷貝
var arr =[{name:`yf`,students:{name:`zs`,age:10,course:{name:`english`}}}]
var deepCopy = function(o) {
    if (o instanceof Array) {
        var n = [];
        for (var i = 0; i < o.length; ++i) {
            n[i] = deepCopy(o[i]);
        }
        return n;

    } else if (o instanceof Object) {
        var n = {}
        for (var i in o) {
            n[i] = deepCopy(o[i]);
        }
        return n;
    } else {
        return o;
    }
}
var cloneArr = deepCopy(arr);
cloneArr[0].students.course.name =`aaaaaaaaaaaa`;
console.log(cloneArr);
console.log(arr);
複製程式碼

Note:此處的判斷,一定要將 o instanceof Array放在o instanceof Object前邊,為什麼呢?英文陣列進行instanceof Object的判斷結果也是true,這就關係到原型鏈的問題了哈。

簡單講一下instanceof 的原理

function instance_of(L, R) {//L 表示左表示式,R 表示右表示式
 var O = R.prototype;// 取 R 的顯示原型
 L = L.__proto__;// 取 L 的隱式原型
 while (true) { 
   if (L === null)  //表示已經取到了原型鏈的最頂端
     return false; 
   if (O === L)// 這裡重點:當 O 嚴格等於 L 時,返回 true 
     return true; 
   L = L.__proto__; 
 } 
}
複製程式碼

詳解一下 [] instanceof Object的比較過程

//而上面說的 [] instanceof Object 返回結果為true
var arr = [1,2,3];
arr instanceof Object 
//首先取出arr.__proto__ = Array.prototype, 
arr.__proto__ === Object.prototype //第一輪比較返回false 
arr.__proto__.__proto__ === Object.prototype //第二輪比較返回true
等於
Array.prototype.__proto__ === Object.prototype //返回true

複製程式碼

為什麼會相等,可以深入學習一下原型鏈。小編下一篇會出相關詳解

相關文章