分類專欄: web前端
版權聲明:本文爲博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/qq_36662470/article/details/81490841
一、堆棧的概念
在計算機領域中,堆棧是兩種數據結構。
- 堆:隊列優先,先進先出;由操作系統自動分配釋放 ,存放函數的參數值,局部變量的值等。其操作方式類似於數據結構中的棧。
- 棧:先進後出;動態分配的空間 一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收,分配方式倒是類似於鏈表。
二、js的數據類型
js的數據類型主要分爲兩種:基本類型值和引用類型值。
- 基本類型值 有5種:undefined,null,boolean,number,string。這五種數據類型是按值訪問的,是存放在棧內存中的簡單數據段,數據大小確定,內存空間大小可以分配。
var str1 = "I am string", num1 = 10, bool1 = true, u1 = undefined, n1 = null; //複製變量值 var str2 = str1, num2 = num1, bool2 = bool1, u2 = u1, n2 = n1; //修改變量值 str2 = "Are you new"; num2 = 20; bool2 = false;
可以看到,基本類型值的複製是值的傳遞,賦值以後二者再無關聯,修改其中一個不會影響另一個。
- 引用類型值: 5種基本類型值以外的數據類型都可以看做是引用類型值,比如array,object等,是保存在堆內存中的對象。js不允許直接訪問堆內存中的位置,也就是說不能直接操作對象的內存空間。在操作對象時,實際是在操作對象的引用而不是實際的對象,是按地址訪問的。
var obj1 = { a: "test a" }, arr1 = [2, 5, 6]; var obj2 = obj1, arr2 = arr1; //修改變量值 obj2.a = "change value"; arr1[1] = 48;
可以看到,直接傳遞引用類性值的時候,傳遞的只是引用,二者指向同一塊內存,所以修改其中一個,必然會引起另一個變量的變化。
在日常的使用中,我們把對象賦值給一個變量時,通常希望得到的是一個跟原對象無關的副本,修改新的變量不影響原對象,因此就有了淺拷貝和深拷貝。
三、淺拷貝和深拷貝
簡單的說,淺拷貝就是隻將對象 最外層 的鍵值複製爲一個新的對象,而深拷貝則會 遞歸複製所有的層 ,直到該鍵的值爲基本類型值。 再簡單點說 ,經過淺拷貝後,新舊變量可能還會有所關聯(既然說了是可能還有所關聯,那也可能毫無關聯吧,這裏的關鍵就在於原對象的複雜程度了);而經過深拷貝後,理論上,新舊變量再無關聯。 注意 ,在進行深拷貝時,層級不宜過多。所以,一般的深拷貝也並不是絕對毫無關聯的。
var obj = { a: "a is a", arr: [ 1, 2, 3] }, obj1 = { ...obj }, //假裝這裏是個淺拷貝 obj2 = JSON.parse(JSON.stringify(obj)); //假裝這裏是深拷貝。 obj1.a = "value a"; obj1.arr[0] = 66;
可以看到,當原對象的值爲 基本類型值 時,淺拷貝和深拷貝並沒有區別;而當原對象的某些值爲 引用類型值 時,如果修改變量的值,淺拷貝會改變原對象的值,而深拷貝則不會。