中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

分析JavaScript淺拷貝和深拷貝

發布時間:2021-11-05 11:07:27 來源:億速云 閱讀:141 作者:iii 欄目:開發技術

本篇內容主要講解“分析JavaScript淺拷貝和深拷貝”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“分析JavaScript淺拷貝和深拷貝”吧!

一、直接賦值

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

示例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,對象作為參數傳遞也是傳遞引用:

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'}

二、淺拷貝

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

let object1 = {
    a: 1,
    b: { // b是對象
        b1: 2
    }
};
object2 = Object.assign({}, object1); // 這里就是淺拷貝,其中的b對象只復制了引用
 
// a是常規類型,不會互相影響
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

如果要實現完整的復制,就要使用深拷貝。

三、深拷貝

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

1. JSON對象的方式

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

沿用上面的例子:

let object1 = {
    a: 1,
    b: { // b是對象
        b1: 2
    }
};
 
object2 = JSON.parse(JSON.stringify(object1)); // 深拷貝
 
// a是常規類型,不會互相影響
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

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

這方法的優點:實現非常簡單。

缺點:

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

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

2. 遞歸復制

因為需要一層一層遞進復制,很容想到用遞歸的方式,參考如下實現:

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

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

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

復制原型對象

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

// 把 let target = {}; 改成如下方式
// 保證原型也進行了復制
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);

查看下兩個對象的原型:

深拷貝復制原型對象:

分析JavaScript淺拷貝和深拷貝

完美復制。

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

到此,相信大家對“分析JavaScript淺拷貝和深拷貝”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

承德市| 彭山县| 南岸区| 土默特右旗| 宝清县| 宜昌市| 池州市| 鄂托克前旗| 沁水县| 崇文区| 田阳县| 章丘市| 铁岭县| 澎湖县| 凤台县| 九寨沟县| 含山县| 嘉峪关市| 太谷县| 新田县| 海原县| 浮山县| 蚌埠市| 阆中市| 兰坪| 襄垣县| 蓝山县| 焦作市| 达州市| 阳信县| 崇州市| 秭归县| 新巴尔虎左旗| 进贤县| 乌兰浩特市| 鄂尔多斯市| 女性| 禹州市| 青冈县| 琼结县| 五大连池市|