亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

淺談JS的淺拷貝和深拷貝(遞歸和樹(shù)遍歷)

cjie / 1326人閱讀

摘要:對(duì)象的特殊性因?yàn)閷?duì)象的是通過(guò)指針仔細(xì)內(nèi)存地址的,所以對(duì)象的拷貝不能像變量一般簡(jiǎn)單的賦值,對(duì)象的賦值只是將指針的地址賦值過(guò)去而已,修改屬性值會(huì)對(duì)所有指向這個(gè)內(nèi)存地址的對(duì)象的屬性值都會(huì)被改變,見(jiàn)下面的例子變量賦值修改不會(huì)對(duì)造成影響對(duì)象賦值修改會(huì)

1.對(duì)象的特殊性

因?yàn)閷?duì)象的是通過(guò)指針仔細(xì)內(nèi)存地址的,所以對(duì)象的拷貝不能像變量一般簡(jiǎn)單的賦值,對(duì)象的賦值只是將指針的地址賦值過(guò)去而已,修改屬性值會(huì)對(duì)所有指向這個(gè)內(nèi)存地址的對(duì)象的屬性值都會(huì)被改變,見(jiàn)下面的例子:

// 變量賦值
var a = 5;
var b = a;
// 修改b不會(huì)對(duì)a造成影響
b=10;
> a
> 5

// 對(duì)象賦值
var obj = {
    a: "5",
    b: "10",
    c: {
        d: 1
    }  
}
var obj1 = obj
// 修改obj1.a會(huì)對(duì)obj.a造成影響
obj1.a = 9
> obj.a
> 9

所以當(dāng)你使用object(array也是object的一種特殊形式)時(shí),想復(fù)制一個(gè)object,但兩個(gè)object互不影響時(shí),這就需要我們說(shuō)的淺拷貝和深拷貝了

2.最簡(jiǎn)單的實(shí)現(xiàn)(有局限性)
// object數(shù)據(jù)中只能有基本的數(shù)據(jù)類型(String,Number,Boolean,Array,object,null,undefined),其它數(shù)據(jù)會(huì)丟失,但不會(huì)報(bào)錯(cuò)
obj1 = JSON.parse(JSON.stringify(obj))
3.淺拷貝

基于Object的特殊性,在對(duì)對(duì)象進(jìn)行簡(jiǎn)單的拷貝,只拷貝第一層級(jí)的屬性,這種拷貝就是淺拷貝。

function Copy(source, obj) {
    for (let key in obj) {
        source[key] = obj[key]
    }
    return source
}

Copy(obj1, obj)
obj1.a=10
obj1.c.d=100
// 淺拷貝對(duì)第一層的屬性進(jìn)行了拷貝,所以obj.a不受影響
> obj.a = 9
// 但是obj.c.d是第二層級(jí)的屬性,它受到了影響,它的值被改變了
> obj.c.d =100
3.深拷貝 3.1遞歸遍歷

注意:遞歸遍歷可能爆棧,一般不會(huì)出現(xiàn)這種情況,除非對(duì)象的深度達(dá)到10000+

// 判斷數(shù)據(jù)類型的方法--更新于2019-03-28
function isType(data, type) {
  return Object.prototype.toString.call(data) === "[object " + type + "]"
}
// extendEasy實(shí)現(xiàn)深拷貝;extendSuper在深拷貝的基礎(chǔ)上實(shí)現(xiàn)多個(gè)繼承類似(source, obj1, obj2, obj3 ...)
function extendSuper () {
  var arg = arguments
  for (let i = 1; i < arg.length; i++) {
    arg[0] = extendEasy(arg[0], arg[i])
  }
  return arg[0]
}

// 實(shí)現(xiàn)深拷貝
function extendEasy (source, obj) {
  for (let key in obj) {
// 原來(lái)使用instanceof判斷類型會(huì)存在BUG
    if (isType("Object",obj[key])) {
      source[key] = {}
      source[key] = extendEasy(source[key], obj[key])
    }
    if (isType(" Array",obj[key])) {
      source[key] = []
      source[key] = extendEasy(source[key], obj[key])
    }
    source[key] = obj[key]
  }
  return source
}
3.2樹(shù)遍歷(推薦)

注意:下面代碼中Object.isType的實(shí)現(xiàn)方式-->https://segmentfault.com/a/11...
深度和廣度:pop跟push決定了深度優(yōu)先,廣度優(yōu)先請(qǐng)用shift和push

/*
* @param target object 非必填,默認(rèn){}
* @param source object 必填
*
* */
function copyObject() {
  let root = {}
  const obj = arguments[arguments.length]
  if(!Object.isType(obj, "Object") && !Object.isType(obj, "Array")) {
    throw "source not Object"
  }
  if(arguments.length >= 2 && (Object.isType(arguments[0], "Object") || Object.isType(arguments[0], "Array"))) {
    root = arguments[0]
  } else {
    if(Object.isType(arguments[0], "Array")) {
      root = []
    }
  }
  // 棧
  const arr = [
    {
      // key: undefined,
      parent: root,
      data: obj
    }
  ]
  while (arr.length) {
    // arr: pop跟push決定了深度優(yōu)先,廣度優(yōu)先請(qǐng)用shift和push
    const o = arr.pop()
    // if(o.key === undefined) {
    //   o
    // }
    for (let item in o.data){
      if (Object.isType(o.data[item], "Array")){
        o.parent[item] = []
        arr.push({
          key: item,
          parent: o.parent[item],
          data: o.data[item]
        })
      }
      else if (Object.isType(o.data[item], "Object")) {
        o.parent[item] = {}
        arr.push({
          key: item,
          parent: o.parent[item],
          data: o.data[item]
        })
      }
      // 如果對(duì)其它類型支持請(qǐng)?jiān)谶@里拓展
      else {
        o.parent[item] = o.data[item]
      }
    }
  }
  return root
}

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/102758.html

相關(guān)文章

  • JavaScript中的淺拷貝和深拷貝

    摘要:在中可以通過(guò)添加一個(gè)參數(shù)來(lái)實(shí)現(xiàn)遞歸,調(diào)用就可以實(shí)現(xiàn)一個(gè)深拷貝。利用序列化實(shí)現(xiàn)一個(gè)深拷貝 在JavaScript中,對(duì)于Object和Array這類引用類型值,當(dāng)從一個(gè)變量向另一個(gè)變量復(fù)制引用類型值時(shí),這個(gè)值的副本其實(shí)是一個(gè)指針,兩個(gè)變量指向同一個(gè)堆對(duì)象,改變其中一個(gè)變量,另一個(gè)也會(huì)受到影響。 這種拷貝分為兩種情況:拷貝引用和拷貝實(shí)例,也就是我們說(shuō)的淺拷貝和深拷貝 淺拷貝(shallow...

    ernest.wang 評(píng)論0 收藏0
  • 淺談JavaScript的淺拷貝與深拷貝

    摘要:引用數(shù)據(jù)類型是存放在堆內(nèi)存中的,變量實(shí)際上是一個(gè)存放在棧內(nèi)存的指針,這個(gè)指針指向堆內(nèi)存中的地址。棧和堆的區(qū)別其實(shí)淺拷貝和深拷貝的主要區(qū)別就是數(shù)據(jù)在內(nèi)存中的存儲(chǔ)類型不同。這里,對(duì)存在子對(duì)象的對(duì)象進(jìn)行拷貝的時(shí)候,就是深拷貝了。 數(shù)據(jù)類型 在開(kāi)始拷貝之前,我們從JavaScript的數(shù)據(jù)類型和內(nèi)存存放地址講起。數(shù)據(jù)類型分為基本數(shù)據(jù)類型 和引用數(shù)據(jù)類型 基本數(shù)據(jù)類型主要包括undefin...

    娣辯孩 評(píng)論0 收藏0
  • JS的淺拷貝和深拷貝

    摘要:說(shuō)明外層數(shù)組拷貝的是實(shí)例說(shuō)明元素拷貝是引用深拷貝在堆中重新分配內(nèi)存,并且把源對(duì)象所有屬性都進(jìn)行新建拷貝,拷貝后的對(duì)象與原來(lái)的對(duì)象完全隔離,互不影響。中的方法可以實(shí)現(xiàn)深拷貝,源碼原理也是遞歸使用淺拷貝。 1.淺拷貝 當(dāng)把數(shù)組或?qū)ο蠛?jiǎn)單賦值給其他變量的時(shí)候,實(shí)際上進(jìn)行的是淺拷貝,淺拷貝是拷貝引用,只是將拷貝后的引用指向同一個(gè)對(duì)象實(shí)例,彼此間的操作還會(huì)互相影響。 分為兩種情況:直接拷貝源對(duì)象...

    xeblog 評(píng)論0 收藏0
  • js的淺拷貝和深拷貝和應(yīng)用場(chǎng)景

    摘要:而大多數(shù)實(shí)際項(xiàng)目中,我們想要的結(jié)果是兩個(gè)變量初始值相同互不影響。所以就要使用到拷貝分為深淺兩種深淺拷貝的區(qū)別淺拷貝只復(fù)制一層對(duì)象的屬性,而深拷貝則遞歸復(fù)制了所有層級(jí)。 為什么會(huì)用到淺拷貝和深拷貝 首先來(lái)看一下如下代碼 let a = b = 2 a = 3 console.log(a) console.log(b) let c = d = [1,2,3] let e = f = {a:...

    MartinDai 評(píng)論0 收藏0
  • js的淺拷貝和深拷貝和應(yīng)用場(chǎng)景

    摘要:而大多數(shù)實(shí)際項(xiàng)目中,我們想要的結(jié)果是兩個(gè)變量初始值相同互不影響。所以就要使用到拷貝分為深淺兩種深淺拷貝的區(qū)別淺拷貝只復(fù)制一層對(duì)象的屬性,而深拷貝則遞歸復(fù)制了所有層級(jí)。 為什么會(huì)用到淺拷貝和深拷貝 首先來(lái)看一下如下代碼 let a = b = 2 a = 3 console.log(a) console.log(b) let c = d = [1,2,3] let e = f = {a:...

    nemo 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<