最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JS中實(shí)現(xiàn)淺拷貝和深拷貝的代碼詳解

 更新時(shí)間:2019年06月05日 11:19:17   作者:撩課學(xué)院  
JavaScript的變量中包含兩種類(lèi)型的值:基本類(lèi)型值 和 引用類(lèi)型值,這篇文章主要介紹了JS中實(shí)現(xiàn)淺拷貝和深拷貝,需要的朋友可以參考下

(一)JS中基本類(lèi)型和引用類(lèi)型

JavaScript的變量中包含兩種類(lèi)型的值:基本類(lèi)型值 和 引用類(lèi)型值,在內(nèi)存中的表現(xiàn)形式在于:前者是存儲(chǔ)在棧中的一些簡(jiǎn)單的數(shù)據(jù)段,后者則是保存在堆內(nèi)存中的一個(gè)對(duì)象。

基本類(lèi)型值

在JavaScript中基本數(shù)據(jù)類(lèi)型有 String , Number , Undefined , Null , Boolean ,在ES6中,又定義了一種新的基本數(shù)據(jù)類(lèi)型 Symbol ,所以一共有6種。

基本類(lèi)型是按值訪(fǎng)問(wèn)的,從一個(gè)變量復(fù)制基本類(lèi)型的值到另一個(gè)變量后,這兩個(gè)變量的值是完全獨(dú)立的,即使一個(gè)變量改變了也不會(huì)影響到第二個(gè)變量。

var str1 = '撩課';
var str2 = str1;
str2 = 'itlike';
console.log(str2); //'itlike'
console.log(str1); //'撩課'

引用類(lèi)型值

引用類(lèi)型值是引用類(lèi)型的實(shí)例,它是保存在堆內(nèi)存中的一個(gè)對(duì)象,引用類(lèi)型是一種數(shù)據(jù)結(jié)構(gòu),最常用的是Object,Array,Function類(lèi)型,此外還有Date,RegExp,Error等。

在ES6中提供了Set,Map2種新的數(shù)據(jù)結(jié)構(gòu)。

(二)JS中如何復(fù)制引用類(lèi)型的

基本類(lèi)型和引用類(lèi)型賦值的差異化
舉個(gè)例子:在下面代碼中,只修改了obj1中的name屬性,卻同時(shí)改變了ob1和obj2中的name屬性。

var obj1 = {'name': '撩課'};
var obj2 = obj1;
obj2.name = '小撩';
console.log(obj1); // {'name': '撩課'}
console.log(obj2); // {'name': '撩課'}

當(dāng)變量復(fù)制引用類(lèi)型值的時(shí)候,同樣和基本類(lèi)型值一樣會(huì)將變量的值復(fù)制到新變量上,不同的是對(duì)于變量的值,它是一個(gè)指針,指向存儲(chǔ)在堆內(nèi)存中的對(duì)象。

因?yàn)?,在JS中,堆內(nèi)存中的對(duì)象無(wú)法直接訪(fǎng)問(wèn),必須要訪(fǎng)問(wèn)這個(gè)對(duì)象在堆內(nèi)存中的地址,然后再按照這個(gè)地址去獲得這個(gè)對(duì)象中的值。

(三)淺拷貝

在JS中,如果屬性是基本類(lèi)型,拷貝的就是基本類(lèi)型的值;如果屬性是引用類(lèi)型,拷貝的就是內(nèi)存地址;所以如果其中一個(gè)對(duì)象改變了這個(gè)地址,就會(huì)影響到另一個(gè)對(duì)象。

下面是JavaScript提供的淺拷貝方法:

Object.assign

ES6中拷貝對(duì)象的方法,接受的第一個(gè)參數(shù)是拷貝的目標(biāo),剩下的參數(shù)是拷貝的源對(duì)象;

語(yǔ)法:Object.assign(target, ...sources)

var p = {
  'name': '張三',
};
var copyP = {};
Object.assign(copyP, p);
console.log(copyP);
console.log(p);

Object.assign是一個(gè)淺拷貝,它只是在根屬性(對(duì)象的第一層級(jí))創(chuàng)建了一個(gè)新的對(duì)象,但是如果屬性的值是對(duì)象的話(huà),只會(huì)拷貝一份相同的內(nèi)存地址。

擴(kuò)展運(yùn)算符

利用擴(kuò)展運(yùn)算符可以在構(gòu)造字面量對(duì)象時(shí),進(jìn)行克隆或者屬性拷貝。語(yǔ)法如下:

var cloneObj = { ...obj };
var obj = {'name': '撩課', 'college': ['H5','JAVA','Python']}
var obj2 = {...obj};
obj.name='小撩';
//{'name': '小撩', 'college': ['H5','JAVA','Python']}
console.log(obj);
//{'name': '撩課', 'college': ['H5','JAVA','Python']}
console.log(obj2); 
obj.college.push('Go');
//{'name': '小撩', 'college': ['H5','JAVA','Python','Go']}
console.log(obj); 
//{'name': '小撩', 'college': ['H5','JAVA','Python','Go']}
console.log(obj2);

擴(kuò)展運(yùn)算符和Object.assign()存在同樣的問(wèn)題,對(duì)于值是對(duì)象的屬性無(wú)法完全拷貝成兩個(gè)不同對(duì)象;

但是如果屬性都是基本類(lèi)型的值的話(huà),使用擴(kuò)展運(yùn)算符更加簡(jiǎn)潔。

(四)深拷貝

淺拷貝只在根屬性上在堆內(nèi)存中創(chuàng)建了一個(gè)新的的對(duì)象,復(fù)制了基本類(lèi)型的值,但是復(fù)雜數(shù)據(jù)類(lèi)型也就是對(duì)象則是拷貝相同的地址。

而深拷貝則是將一個(gè)對(duì)象從內(nèi)存中完整的拷貝一份出來(lái),從堆內(nèi)存中開(kāi)辟一個(gè)新的區(qū)域存放新對(duì)象,且修改新對(duì)象不會(huì)影響原對(duì)象。

JSON.stringify

JSON.stringify()是目前開(kāi)發(fā)過(guò)程中最常用的深拷貝方式,原理是把一個(gè)對(duì)象序列化成為一個(gè)JSON字符串,將對(duì)象的內(nèi)容轉(zhuǎn)換成字符串的形式再保存在內(nèi)存中,再用JSON.parse()反序列化將JSON字符串變成一個(gè)新的對(duì)象。

舉個(gè)例子:

var obj = {
  name: '撩課',
  age: 18,
  friends: ['小花', '小黑'],
  goodF: {
    name: '小撩',
    age: 19,
    address: '上海',
    pets: [{name: '土豆'}, {name: '馬鈴薯'}]},
  bir: new Date()
};

var newObj = JSON.parse(JSON.stringify(obj));
obj.goodF.pets[0].name = '旺財(cái)';
console.log(newObj);
console.log(obj);

使用JSON.stringify實(shí)現(xiàn)深拷貝有幾點(diǎn)要注意:

1)拷貝的對(duì)象的值中如果有函數(shù),undefined,symbol,經(jīng)過(guò)JSON.stringify()序列化后的JSON字符串中這個(gè)鍵值對(duì)會(huì)消失;

無(wú)法拷貝不可枚舉的屬性,無(wú)法拷貝對(duì)象的原型鏈
3)拷貝Date引用類(lèi)型會(huì)變成字符串

4)拷貝RegExp引用類(lèi)型會(huì)變成空對(duì)象

對(duì)象中含有NaN、Infinity和-Infinity,則序列化的結(jié)果會(huì)變成null

遞歸實(shí)現(xiàn)深拷貝

具體實(shí)現(xiàn)如下:

/**
 * 輔助函數(shù), 判定是否是對(duì)象
 * @param obj
 * @returns {boolean}
 */
function isObj(obj) {
  return obj instanceof Object;
}

/**
 * 深拷貝fromObj面的所有屬性/值, 到toObj對(duì)象里面
 * @param fromObj 拷貝對(duì)象
 * @param toObj  目標(biāo)對(duì)象
 */
function deepCopyObj2NewObj(fromObj, toObj) {
  for (var key in fromObj) {
    if(fromObj.hasOwnProperty(key)){
      var fromValue = fromObj[key];
      // 如果是值類(lèi)型,那么就直接拷貝賦值
      if (!isObj(fromValue)) {
        toObj[key] = fromValue;
      } else {
        // 如果是引用類(lèi)型,那么就再調(diào)用一次這個(gè)方法,
        // 去內(nèi)部拷貝這個(gè)對(duì)象的所有屬性
        // fromValue是什么類(lèi)型, 創(chuàng)建一個(gè)該類(lèi)型的空對(duì)象
        var tmpObj = new fromValue.constructor;

        // console.log(tmpObj);
        // debugger;
        deepCopyObj2NewObj(fromValue, tmpObj);
        toObj[key] = tmpObj;
      }
    }
  }
}

(五)總結(jié)

1)在日常開(kāi)發(fā)中一般并不需要拷貝很多特殊的引用類(lèi)型,深拷貝對(duì)象使用JSON.stringify是最直接和簡(jiǎn)單的方法。

2)實(shí)現(xiàn)一個(gè)完整的深拷貝是非常復(fù)雜的,需要考慮到很多邊界情況。對(duì)于特殊的引用類(lèi)型有拷貝需求的話(huà),建議借助第三方完整的庫(kù)。

以上所述是小編給大家介紹的JS中實(shí)現(xiàn)淺拷貝和深拷貝的代碼詳解,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺(jué)得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!

相關(guān)文章

  • JS數(shù)組的常用10種方法詳解

    JS數(shù)組的常用10種方法詳解

    這篇文章主要介紹了JS數(shù)組的常用10種方法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • js中checkbox的使用教程(取值、賦值、判斷是否選中)

    js中checkbox的使用教程(取值、賦值、判斷是否選中)

    在checkbox的使用中,我們經(jīng)常遇到需要全選或者單選的情況,下面這篇文章主要給大家介紹了關(guān)于js中checkbox使用(取值、賦值、判斷是否選中)的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-07-07
  • swiper.js插件實(shí)現(xiàn)pc端文本上下滑動(dòng)功能示例

    swiper.js插件實(shí)現(xiàn)pc端文本上下滑動(dòng)功能示例

    這篇文章主要介紹了swiper.js插件實(shí)現(xiàn)pc端文本上下滑動(dòng)功能,結(jié)合實(shí)例形式分析了swiper.js插件的具體引用與相關(guān)使用技巧,需要的朋友可以參考下
    2018-12-12
  • JS中instanceof的使用小結(jié)

    JS中instanceof的使用小結(jié)

    在JavaScript中,instanceof是判斷引用類(lèi)型的重要工具,本文就來(lái)介紹一下JS中instanceof的使用小結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2026-03-03
  • JSON 基本使用教程

    JSON 基本使用教程

    JSON是一種輕量級(jí)(Light-Meight)、基于文本的(Text-Based)、可讀的(Human-Readable)格式,這篇文章主要介紹了JSON 基本使用教程,需要的朋友可以參考下
    2023-02-02
  • 微信小程序引入外部icon(阿里巴巴矢量圖標(biāo))的全過(guò)程

    微信小程序引入外部icon(阿里巴巴矢量圖標(biāo))的全過(guò)程

    在小程序中,有默認(rèn)的圖標(biāo)icon組件,但你會(huì)發(fā)現(xiàn)它的圖標(biāo)樣式很少,可能很多時(shí)候并不能滿(mǎn)足我們的需求,所以這篇文章主要給大家介紹了關(guān)于微信小程序引入外部icon(阿里巴巴矢量圖標(biāo))的相關(guān)資料,需要的朋友可以參考下
    2022-09-09
  • JavaScript使用readAsDataUrl方法預(yù)覽圖片

    JavaScript使用readAsDataUrl方法預(yù)覽圖片

    這篇文章主要為大家詳細(xì)介紹了JavaScript使用readAsDataUrl方法預(yù)覽圖片,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • w3c聲明下可運(yùn)行 兼容性比較好的js對(duì)聯(lián)廣告集合

    w3c聲明下可運(yùn)行 兼容性比較好的js對(duì)聯(lián)廣告集合

    最近有美工朋友找我們要兼容性比較好的對(duì)聯(lián)廣告代碼,我們給他一個(gè)他竟然不能運(yùn)行,經(jīng)過(guò)排查,這是因?yàn)楝F(xiàn)在的廣告也用了一樣代碼,函數(shù)命名重復(fù)。
    2011-07-07
  • 微信小程序?qū)崿F(xiàn)Swiper輪播圖效果

    微信小程序?qū)崿F(xiàn)Swiper輪播圖效果

    這篇文章主要介紹了微信小程序?qū)崿F(xiàn)Swiper輪播圖效果,文中示例代碼介紹的非常詳細(xì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • 微信小程序自定義頂部導(dǎo)航組件

    微信小程序自定義頂部導(dǎo)航組件

    這篇文章主要為大家詳細(xì)介紹了微信小程序自定義頂部導(dǎo)航組件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07

最新評(píng)論

宜丰县| 建平县| 襄汾县| 西充县| 洪雅县| 荔波县| 中卫市| 元江| 日照市| 玉门市| 都安| 建湖县| 商水县| 江门市| 灵石县| 石屏县| 无棣县| 安远县| 繁昌县| 剑阁县| 芦溪县| 临夏市| 诸暨市| 崇州市| 陈巴尔虎旗| 庆元县| 宝鸡市| 太仆寺旗| 平谷区| 永城市| 曲周县| 宜黄县| 筠连县| 白朗县| 喀喇沁旗| 海口市| 台安县| 长兴县| 集安市| 江北区| 南江县|