首頁 >web前端 >js教程 >js實作深淺拷貝方法

js實作深淺拷貝方法

小云云
小云云原創
2018-03-16 16:44:022699瀏覽

說起深淺拷貝,我覺得需要理清楚 值類型引用類型,本文主要和大家分享js實現深淺拷貝方法,希望能幫助到大家。

值型別

所謂值型別undefinednullnumberstringboolean 等五種基本資料類型, 應該還有一個Symbol類型。

值類型的資料儲存在堆疊記憶體中

值類型 中修改值相當於重新在堆疊記憶體中開闢了一個新的儲存空間,類似:

js實作深淺拷貝方法

用程式碼解釋就是:

var num1 = 5var num2 = num1

值類型的值不可改變

javascript中的原始值(undefined、null、布林值、數字和字串)與物件(包括陣列和函數)有著根本區別。原始值是不可更改的:任何方法都無法更改(或“突變”)一個原始值。對數字和布林值來說顯然如此—— 改變數字的值本身就說不通,而對字串來說就不那麼明顯了,因為字串看起來像由字元組成的數組,我們期望可以透過指定索引來假改字串中的字元。實際上,javascript 是禁止這樣做的。字串中所有的方法看上去回傳了一個修改過的字串,實際上回傳的是一個新的字串值。

var str = 'abc'str[0] = 'd'console.log(str)  // 'abc'

值類型的比較是對值的比較
值類型的比較是值的比較,只要它們的值相等就認為他們是相等的

var a = 1;var b = 1;console.log(a === b);//true

引用型別

引用型別的資料存放在堆疊記憶體中
引用型別的值存放在堆疊記憶體中,變數保存的是一個存放在堆疊內存,指向堆記憶體的指標。

var person1 = {name:'jozo'};var person2 = {name:'xiaom'};var person3 = {name:'xiaoq'};

js實作深淺拷貝方法

引用類型的值可以改變
引用類型是可以直接改變其值的

 var a = [1,2,3];
 a[1] = 5;
 console.log(a[1]); // 5

引用類型的比較是引用的比較
所以每次我們對js 中的引用類型進行操作的時候,都是操作其物件的參考(保存在堆疊記憶體中的指標),所以比較兩個引用類型,是看其的引用是否指向同一個物件。

var a = [1,2,3];var b = [1,2,3];console.log(a === b); // falsevar a = [1, 2, 3]var b = aconsole.log(a === b)  // true

傳值與傳址

了解了基本資料型別與參考型別的差異之後,我們就應該可以明白傳值與傳址的差異了。
在我們進行賦值操作的時候,基本資料型別的賦值(=)是在記憶體中新開闢一段堆疊內存,然後再把再將值賦值到新的棧中

var a = 10;var b = a;

a ++ ;
console.log(a); // 11console.log(b); // 10

js實作深淺拷貝方法

所以說,基本類型的賦值的兩個變數是兩個獨立相互不影響的變數。

但是引用型別的賦值是傳址。只是改變指標的指向,例如,也就是說引用類型的賦值是物件保存在堆疊中的位址的賦值,這樣的話兩個變數就指向同一個對象,因此兩者之間操作互相有影響。

var a = {}; // a保存了一个空对象的实例var b = a;  // a和b都指向了这个空对象a.name = 'jozo';
console.log(a.name); // 'jozo'console.log(b.name); // 'jozo'b.age = 22;
console.log(b.age);// 22console.log(a.age);// 22console.log(a == b);// true

js實作深淺拷貝方法

淺拷貝

js實作深淺拷貝方法

實作

function shallowCopy (src) {
    let  new = {}    for (let i in src) {        if (src.hasOwnProperty(i)) {            new[i] = src[i]
        }
    }    return new}

深拷貝

一種騷操作是利用JSON.parse 和JSON.stringify

var a = {
    name: 'SpawN',
    age: 28}var b = JSON.parse(JSON.stringify(a))
b.name = 'Johnny.R'console.log(a.name)  // 'SpawN'

另外一種是科班操作,也就是常規操作,就是利用遞歸,來遍歷目標對像下的所有屬性

function deepCopy(obj) {
    if (typeof obj !== 'object') return
    // 初始化
    var newObj = obj instanceof Array ? [] : {}    for (let k in obj) {        if (obj.hasOweProperty(k)) {
            newObj[k] = typeof obj[k] === 'object' ? agruments.callee(obj[k]) : obj[k]
        }
    }    return newObj
}

這裡只是實現了基本的深拷貝,對一些邊界並沒有進行妥善的處理。基本想法就是透過for in 循環,當值為物件的時候,再遞歸進行for in迴圈。

相關推薦:

js陣列與物件的深淺拷貝詳解

如何實作陣列與物件的深淺拷貝

#深淺拷貝入門教學:10個深淺拷貝零基礎入門教學推薦

#

以上是js實作深淺拷貝方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn