老生常談之js深拷貝與淺拷貝


前言

經常會在一些網站或博客看到“深克隆”,“淺克隆”這兩個名詞,其實這個很好理解,今天我們就在這里分析一下js深拷貝和淺拷貝

淺拷貝

我們先以一個例子來說明js淺拷貝:

var n = {a: 1, b: 2}
var m = n
m.a = 12
console.log(n.a) // ?

上面顯然 n.a 的值會變為 12,這就是js淺拷貝。淺拷貝只是拷貝的指向對象的指針,本質上還是指向同一個對象。

深拷貝

同樣我們還是以一個例子來說明啥叫 js deep clone

var n = {a: 1, b: 2}
var m = {a: n.a, b: n.b}
m.a = 12
console.log(n.a) // ?

上面的輸出結果顯然還是 1 ,m 和 n 雖然所有的屬性和值全部相同,但是它們是兩個不同的對象,它們在堆內存中占據兩塊不同的內存地址,這就是深度拷貝。深度拷貝就是完全復制一個新的對象出來,它們在堆內存中完全占據兩個不同的內存地址。

js 實現深拷貝

簡單一維數據結構

  1. 手動直接賦值

上面的 深拷貝 例子

  1. 利用 ES6 Object.assign() 方法

const obj = {name: 'cc', age: 24}
const newObj = Object.assign({}, obj)
obj.name = 'cc1'
newObj.name ? // cc

二維的數據結構及以上

  1. 簡單粗暴的方式:JSON.parse(JSON.stringify(obj))

缺點:它會對對於正則表達式類型、函數類型等無法進行深拷貝,而且會直接丟失相應的值,還有就是它會拋棄對象的 constructor

var obj = { a: {a: "cc"}, b: 123 }
var newObj = JSON.parse(JSON.stringify(obj))
newObj.b = 1234
console.log(obj)   // {a: {a: 'cc'}, b: 123}
console.log(newObj);    // {a: {a: 'cc'}, b: 1234}
  1. 利用 jQuery

// 淺拷貝
var newObj = $.extend({}, obj)

// 深拷貝
var newObj = $.extend(true, {}, obj) // 要求第一個參數必須為true
  1. 自己動手實現一個簡單深拷貝函數
function deepClone(obj){
  if(typeof obj !== "object" || obj === null) return    
  let newObj = obj instanceof Array ? [] : {}
  for(let key in obj){
     if(obj.hasOwnProperty(key)){
        newObj[key] = typeof obj[key] === "object" && obj[key] !== null ? deepClone(obj[key]) : obj[key]
    }      
  }  
  return newObj
}
let obj = {a: 1, b: function(){}, c: {d: 2}}
deepClone(obj)  // {a: 1, b: function(){}, c: {d: 2}}

對於深拷貝來說最常用的就是這些方法,當然還有其他的一些庫,比如 deepCopylodash等,這里就不深究。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM