欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺談JavaScript淺拷貝和深拷貝

 更新時間:2021年11月05日 09:04:44   作者:快樂編程  
這篇文章主要介紹了淺談JavaScript淺拷貝和深拷貝,javascript中的對象是引用類型,在復(fù)制對象的時候就要考慮是用淺拷貝還是用深拷貝。接下來一起聊聊吧,感興趣的小伙伴也可以參考一下

網(wǎng)上關(guān)于這個話題,討論有很多了,根據(jù)各路情況我自己整理了一下,最后還是能接近完美的實現(xiàn)深拷貝,歡迎大家討論。

javascript中的對象是引用類型,在復(fù)制對象的時候就要考慮是用淺拷貝還是用深拷貝。

一、直接賦值

對象是引用類型,如果直接賦值給另外一個對象,那么只是賦值一個引用,實際上兩個變量指向的同一個數(shù)據(jù)對象,如果其中一個對象的屬性變更,那么另外一個也會變更。

示例1,簡單示例:

let human1 = {
    id: 1,
    name: "happy"
};
human2 = human1; // 這里就是直接賦值
 
console.log(human1); // {id: 1, name: 'happy'}
console.log(human2); // {id: 1, name: 'happy'}
 
// 更改human1的名稱,human2的也會更改
human1.name = "life";
console.log(human1); // {id: 1, name: 'life'}
console.log(human2); // {id: 1, name: 'life'}

示例2,對象作為參數(shù)傳遞也是傳遞引用:

let human1 = {
    id: 1,
    name: "happy"
};
 
console.log(human1); // {id: 1, name: 'happy'}
 
function foo(human) {
    // 這里更改了human對象的名稱
    human.name = "life";
}
foo(human1); // 傳遞對象是傳遞引用
 
console.log(human1); // {id: 1, name: 'life'}

二、淺拷貝

淺拷貝只是復(fù)制了對象的第一層,如果第一層的屬性值是對象,那么該屬性也只是復(fù)制了一個引用。

let object1 = {
    a: 1,
    b: { // b是對象
        b1: 2
    }
};
object2 = Object.assign({}, object1); // 這里就是淺拷貝,其中的b對象只復(fù)制了引用
 
// a是常規(guī)類型,不會互相影響
object1.a = 10;
console.log(object1.a); // 10
console.log(object2.a); // 1
 
// b是對象,會互相影響
object1.b.b1 = 20;
console.log(object1.b.b1); // 20
console.log(object2.b.b1); // 20


如果要實現(xiàn)完整的復(fù)制,就要使用深拷貝。

三、深拷貝

森拷貝就是不光是一層要復(fù)制,里面的層如果是對象也要進行復(fù)制。

1. JSON對象的方式

如果對象可以確認是JSON對象,那么可以用JSON對象的方式。

沿用上面的例子:

let object1 = {
    a: 1,
    b: { // b是對象
        b1: 2
    }
};
 
object2 = JSON.parse(JSON.stringify(object1)); // 深拷貝
 
// a是常規(guī)類型,不會互相影響
object1.a = 10;
console.log(object1.a); // 10
console.log(object2.a); // 1
 
// b是對象,也不會互相影響
object1.b.b1 = 20;
console.log(object1.b.b1); // 20
console.log(object2.b.b1); // 2


這邊深拷貝的原理其實就是先把對象轉(zhuǎn)成json字符串,然后再轉(zhuǎn)成json對象,中間轉(zhuǎn)成json字符串后就和原來的對象沒有關(guān)系了。

這方法的優(yōu)點:實現(xiàn)非常簡單。

缺點:

如果有屬性值是函數(shù)的話,那么無法進行復(fù)制,數(shù)據(jù)會丟失。
另外原型對象無法進行復(fù)制。

所以這種方式只適合對象確認是一個純粹的json數(shù)據(jù)。

2. 遞歸復(fù)制

因為需要一層一層遞進復(fù)制,很容想到用遞歸的方式,參考如下實現(xiàn):

function deepCopy(source) {
    // 如果不是對象或者是null則直接返回
    if (typeof source !== 'object' || source === null) {
        return source;
    }
 
    let target = {};
    // 遍歷復(fù)制屬性
    for (let k in source) {
        if (!source.hasOwnProperty(k)) {
            continue;
        }
 
        if (typeof source[k] === 'object') { // 如果是對象,則遞歸復(fù)制
            target[k] = deepCopy(source[k]);
            continue;
        }
 
        let descriptor = Object.getOwnPropertyDescriptor(source, k);
        Object.defineProperty(target, k, descriptor);
    }
 
    return target;
}

因為是一層一層復(fù)制,所以復(fù)制完成后,兩個對象不會互相影響,并且也可以支持方法。

let object1 = {
    a: 1,
    b: { // b是對象
        b1: 2
    },
    f: function() { // f是方法
        console.log(3);
    }
};
object2 = deepCopy(object1); // 深拷貝,也可以復(fù)制函數(shù)了。
object1.f(); // 3
object2.f(); // 3
 
// b是對象,也不會互相影響
object1.b.b1 = 20;
console.log(object1.b.b1); // 20
console.log(object2.b.b1); // 2


復(fù)制原型對象

但是這個方法還存在一個問題,就是原型對象無法復(fù)制,稍微改進一下:

// 把 let target = {}; 改成如下方式
// 保證原型也進行了復(fù)制
let target = Object.create(Object.getPrototypeOf(source));


這樣就可以了,來個示例驗證一下:

function Human() {
    this.id = 1;
}
Human.prototype.bar = function() {
    console.log("bar");
};
 
let human1 = new Human();
human2 = deepCopy(human1);
 
console.log("human1", human1);
console.log("human2", human2);


查看下兩個對象的原型:

深拷貝復(fù)制原型對象:

完美復(fù)制。

當(dāng)然這樣的方法也存在一個問題,就是遞歸本身存在如果層次過深,容易造成棧溢出的問題。但是在實務(wù)中也建議不要復(fù)制非常大的對象,應(yīng)該有另外好的解決方法。

到此這篇關(guān)于淺談JavaScript淺拷貝和深拷貝的文章就介紹到這了,更多相關(guān)JavaScript淺拷貝和深拷貝內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

參考文檔:

JS實現(xiàn)深拷貝:https://www.cnblogs.com/dobeco/p/11295316.html
Object.assign():https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
Object.create():https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/create
Object.getPrototypeOf():https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf
Object.defineProperty():https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
Object.getOwnPropertyDescriptor():https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor
hasOwnProperty():https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty

相關(guān)文章

  • Javascript中bind()方法綁定函數(shù)的使用與實現(xiàn)

    Javascript中bind()方法綁定函數(shù)的使用與實現(xiàn)

    這篇文章主要為大家介紹了Javascript中bind()方法綁定函數(shù)的使用與實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-06-06
  • 前端常見跨域解決方案(全)

    前端常見跨域解決方案(全)

    這篇文章主要介紹了前端常見跨域解決方案的相關(guān)內(nèi)容,包括對跨域的解釋,常見跨域場景以及跨域解決方案,內(nèi)容豐富,需要的朋友可以參考下。
    2017-09-09
  • 判斷Spartacus?SSR的Transfer?State是否正常工作技巧

    判斷Spartacus?SSR的Transfer?State是否正常工作技巧

    這篇文章主要為大家介紹了判斷Spartacus?SSR的Transfer?State是否正常工作技巧,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-10-10
  • 微信小程序 實現(xiàn)拖拽事件監(jiān)聽實例詳解

    微信小程序 實現(xiàn)拖拽事件監(jiān)聽實例詳解

    這篇文章主要介紹了微信小程序 實現(xiàn)拖拽事件監(jiān)聽實例詳解的相關(guān)資料,在開發(fā)不少應(yīng)用或者軟件都要用到這樣的方法,這里就對微信小程序?qū)崿F(xiàn)該功能進行介紹,需要的朋友可以參考下
    2016-11-11
  • JavaScript+HTML實現(xiàn)學(xué)生信息管理系統(tǒng)

    JavaScript+HTML實現(xiàn)學(xué)生信息管理系統(tǒng)

    這篇文章主要介紹了JavaScript實現(xiàn)學(xué)生信息管理系統(tǒng),文中有非常詳細的代碼示例,對正在學(xué)習(xí)js的小伙伴們有一定的幫助,需要的朋友可以參考下
    2021-04-04
  • nuxt.js 多環(huán)境變量配置

    nuxt.js 多環(huán)境變量配置

    這篇文章主要介紹了nuxt.js 多環(huán)境變量配置,一般在香米開發(fā)中會有三個環(huán)境開發(fā)環(huán)境也叫測試環(huán)境(test) 、RC環(huán)境也叫預(yù)發(fā)布環(huán)境(rc) 、線上環(huán)境(production) 下面來看看文章內(nèi)容的詳細介紹,需要的朋友可以參考一下
    2021-11-11
  • 可拖動窗口,附帶鼠標(biāo)控制漸變透明,開啟關(guān)閉功能

    可拖動窗口,附帶鼠標(biāo)控制漸變透明,開啟關(guān)閉功能

    可拖動窗口,附帶鼠標(biāo)控制漸變透明,開啟關(guān)閉功能...
    2006-06-06
  • 微信小程序 生命周期詳解

    微信小程序 生命周期詳解

    這篇文章主要介紹了微信小程序 生命周期的相關(guān)資料,創(chuàng)建、到開始、暫停、喚起、停止、卸載等過程,需要的朋友可以參考下
    2016-10-10
  • JS代理對象Proxy初體驗簡單的數(shù)據(jù)驅(qū)動視圖

    JS代理對象Proxy初體驗簡單的數(shù)據(jù)驅(qū)動視圖

    這篇文章主要為大家介紹了JS代理對象Proxy初體驗簡單的數(shù)據(jù)驅(qū)動視圖,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • '2'>'10'==true?解析JS如何進行隱式類型轉(zhuǎn)換

    '2'>'10'==true?解析JS如何進行隱式類型轉(zhuǎn)換

    這篇文章主要為大家介紹了'2'>'10'==true?解析JS如何進行隱式類型轉(zhuǎn)換示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-09-09

最新評論