JavaScript深淺拷貝

原文鏈接 http://blog.poetries.top/2018/12/21/js-deep-copy/

關(guān)注公眾號獲取更多資訊

一、前言

js中,變量的類型可以大致分成兩種:基本數(shù)據(jù)類型和引用數(shù)據(jù)類型,其中基本數(shù)據(jù)類型指的是簡單的數(shù)據(jù)段,包括:

  • undefined
  • Null
  • Boolean
  • Number
  • String(字符串在一些其他語言中是被當(dāng)做對象使用的,屬于引用類型,但在js里是基本類型)

而引用類型的值指的是可能包含多個(gè)值的對象。本質(zhì)上,是因?yàn)榛緮?shù)據(jù)類型保存在棧內(nèi)存,而引用類型保存在堆內(nèi)存中。為什么要分兩種保存方式呢? 根本原因在于保存在棧內(nèi)存的必須是大小固定的數(shù)據(jù),引用類型的大小不固定,只能保存在堆內(nèi)存中,但是我們可以把它的地址寫在占內(nèi)存中以供我們訪問

var a = 1;//定義了一個(gè)number類型
var obj1 = {//定義了一個(gè)objr類型
    name:'obj'
};

在執(zhí)行這段代碼后,內(nèi)存空間里是這樣的

image.png

因?yàn)檫@種保存方式的存在,所以我們在操作變量的時(shí)候,如果是基本數(shù)據(jù)類型,則按值訪問,操作的就是變量保存的值;如果是引用類型的值,我們只是通過保存在變量中的引用類型的地址類操作實(shí)際對象。從而也引出了所謂的深淺復(fù)制問題

二、淺拷貝

方法一

// 假設(shè)有兩個(gè)對象

var objA = {
  a: 'aa',
  b: 'bb'
};
var objB = {};
// 現(xiàn)在想把對象A的值復(fù)制給B,由于對象A的兩個(gè)值都是原始類型,用淺復(fù)制即可

function copy(sub, sup) {
  for (var key in sup) {
    sub[key] = sup[key];
  }
}
copy(objB, objA);

方法二

Object.assign() (兼容性不好)

方法三

_.clone()

方法四

數(shù)組中concatslice方法

方法五

ES6展開運(yùn)算

var arr = [{name:'poetries',age:22}]

var target = [...arr]

三、深拷貝

簡單來說深復(fù)制就是當(dāng)遇到值是對象類型的時(shí)候就再運(yùn)行一遍復(fù)制

方法一 JSON.parse(JSON.stringify(obj))

簡單粗暴又有點(diǎn)dirty,但是能滿足日常需求,只能處理json能理解的數(shù)據(jù)格式,當(dāng)然不包括函數(shù)了,性能也沒有特別好

方法二 lodash —— _.cloneDeep()

很好地兼容了ES6的新引用類型,而且處理了環(huán)型對象的情況

方法三 jQuery —— .clone() /.extend()

源碼適合初學(xué)者學(xué)習(xí),比較好理解

方法四 自己實(shí)現(xiàn)一個(gè)

function deepCopy (obj) {
    var result;

    //引用類型分?jǐn)?shù)組和對象分別遞歸
    if (Object.prototype.toString.call(obj) == '[object Array]') {
      result = []
      for (i = 0; i < obj.length; i++) {
        result[i] = deepCopy(obj[i])
      }
    } else if (Object.prototype.toString.call(obj) == '[object Object]') {
      result = {}
      for (var attr in obj) {
        result[attr] = deepCopy(obj[attr])
      }
    }
    //值類型直接返回
    else {
      return obj
    }
    return result
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • underscore 的源碼中,有很多地方用到了 Array.prototype.slice() 方法,但是并沒有...
    theCoder閱讀 676評論 0 1
  • 簡單講呢,深淺拷貝,都是進(jìn)行復(fù)制,那么區(qū)別主要在于復(fù)制出來的新對象和原來的對象是否會(huì)互相影響,改一個(gè),另一個(gè)也會(huì)變...
    _千尋瀑_閱讀 302評論 0 2
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,641評論 1 32
  • Javascript有六種基本數(shù)據(jù)類型(也就是簡單數(shù)據(jù)類型),它們分別是:Undefined,Null,Boole...
    XMUBeike閱讀 336評論 0 0
  • 心里有了疑問, 便會(huì)經(jīng)常想起。 當(dāng)我每次把這疑問向父母問起, 他們都會(huì)大聲訓(xùn)斥我, 讓我不要再有這種愚蠢的想法; ...
    空空丨如然閱讀 163評論 0 0

友情鏈接更多精彩內(nèi)容