JavaScript 深度拷貝和淺拷貝

admin發表於2018-09-26

拷貝是非常容易理解的概念,因為現實生活中拷貝操作實在太多。

JavaScript中的操作是將一個資料結構中的資料複製到另一個資料結構。

比如將一個物件中的屬性拷貝到另一個物件中。

程式碼例項如下:

[JavaScript] 純文字檢視 複製程式碼執行程式碼
let target = {
    webName: "螞蟻部落",
}
let webUrl = {
  url:"www.softwhy.com"
}
let web = Object.assign(target, webUrl);
console.log(web);
console.log(web==target);

程式碼執行效果截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201809/26/120433fft1rt8xqqh5bz3u.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

關於Object.assign方法的使用可以參閱Object.assign()方法一章節。

通過Object.assign方法將webUrl中的屬性拷貝到target物件中。

特別說明:Object.assign方法進行淺拷貝。

JavaScript存在兩種拷貝方式:

(1).淺拷貝。

(2).深度拷貝。

一.淺拷貝:

淺拷貝會將值型別資料拷貝到目標物件,但是引用型別資料只拷貝其引用地址,也就是資料的儲存地址。

關於引用型別資料和值型別資料參閱JavaScript值型別和引用型別一章節。

上面程式碼中,源物件webUrl只包含值型別資料,無所謂淺拷貝或深度拷貝。

再來看一段程式碼例項:

[JavaScript] 純文字檢視 複製程式碼執行程式碼
let target = {
  webName: "螞蟻部落"
}
let source = {
  url:"www.softwhy.com",
  num: {
    x: 1,
    y: 2
  }
}
var web = Object.assign(target, source);
console.log(web==target);
console.log(web);

程式碼執行效果截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201809/26/120542p0rujofoog6rao7l.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

程式碼分析如下:

(1).通過Object.assign方法將source物件的屬性拷貝到target物件。

(2).source物件中,url屬性值是值型別資料,num屬性值是引用型別資料。

(3).值型別資料會實實在在拷貝到目標物件中,但是引用型別資料僅拷貝其引用地址,執行效果截圖中,貌似num屬性所指向的物件被拷貝到了target物件中,其實不然,由於Object.assign是淺拷貝,所以僅拷貝物件的引用地址。也就是說target物件和source物件中的num屬性指向同一個物件。

程式碼證實如下:

[JavaScript] 純文字檢視 複製程式碼執行程式碼
let target = {
  webName: "螞蟻部落"
}
let source = {
  url:"www.softwhy.com",
  num: {
    x: 1,
    y: 2
  }
}
var web = Object.assign(target, source);
source.num.x=10;
console.log(target.num.x);

程式碼執行效果截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201809/26/120627cc38uozpw28c83c2.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

上述程式碼中,修改source物件num屬性所指向物件的x屬性值,但是target物件的num屬性所指向物件的x屬性值同步發生了改變,由此可見,淺拷貝僅僅是拷貝引用型別資料的地址。

二.深度拷貝:

與淺拷貝不同,深度拷貝不但將值型別資料拷貝到目標物件,也會將引用型別資料拷貝到目標物件。

程式碼例項如下:

[JavaScript] 純文字檢視 複製程式碼
let source = {
  url:"www.softwhy.com",
  num: {
    x: 1,
    y: 2
  }
}

深度拷貝會將url和num屬性拷貝到目標物件,與淺拷貝不同的是,深度拷貝會將num屬性所指向的物件拷貝一份到目標物件,而不是僅僅拷貝物件引用地址。

程式碼例項如下:

[JavaScript] 純文字檢視 複製程式碼執行程式碼
let target = {
  webName: "螞蟻部落"
}
let source = {
  url:"www.softwhy.com",
  num: {
    x: 1,
    y: 2
  }
}
function deepCopy(target, source) {
  for (var prop in source) {
    if (typeof source[prop] === 'object') {
      target[prop] = (source[prop].constructor === Array) ? [] : {};
     deepCopy(target[prop], source[prop]);
    } 
     else {
      target[prop] = source[prop];
    }
  }
  return target; 
}
console.log(deepCopy(target, source));
source.num.x=10;
console.log(target.num.x);

程式碼執行效果截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201809/26/120720gi7i9hj071j1qy0j.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

可以看到,修改source物件的num所指向物件的屬性值,並不會對target物件產生影響。

相關文章