目錄
數據類型介紹
基本數據類型(Primitive Types)
引用數據類型(Reference Types)
淺拷貝
深拷貝
利用JSON的序列化和反序列化實現深拷貝
遞歸實現深拷貝
第三方庫lodash的cloneDeep
函數緩存的概念
?實現方法
數據類型介紹
要想了解深淺拷貝,首先得知道有哪些數據類型。在Javascript中,存在兩大數據類型:
基本數據類型(Primitive Types)
JavaScript的基本數據類型包括以下六種:
- Number: 用于表示整數或浮點數。例如:
42
、3.14
。 - String: 用于表示文本數據。例如:
"hello"
、'world'
。 - Boolean: 表示邏輯值,只有
true
和false
兩種。 - Undefined: 表示變量未定義或未賦值。例如:
let a;
,此時a
為undefined
。 - Null: 表示空值,通常用于明確賦空值的情況。例如:
let b = null;
。 - Symbol(ES6新增):表示唯一且不可變的值,通常用于對象屬性的鍵。例如:
Symbol('id')
。
基本數據類型的特點是不可變,直接存儲在棧內存中。
引用數據類型(Reference Types)
引用數據類型主要包括以下兩種:
- Object: 用于存儲鍵值對或復雜數據結構。例如:
{ name: "Alice", age: 25 }
。 - Array: 是特殊的對象,用于存儲有序數據。例如:
[1, 2, 3]
。 - Function: 也是對象的一種,可以被調用執行。例如:
function() { return "hello"; }
。 - Date、RegExp等內置對象。
引用數據類型的特點是可變,數據存儲在堆內存中,變量存儲的是指向堆內存的地址。
在編程中,基本數據類型通常不涉及深拷貝或淺拷貝的概念。所以面試常問的深淺拷貝指的是針對引用數據的處理。
淺拷貝
僅復制對象的頂層屬性,如果屬性是引用類型(如數組、對象),則復制的是引用而非實際對象。因此,修改拷貝后的引用類型屬性會影響原對象。
實現淺拷貝的方式有很多,舉幾個案例:
// Object.assign()
// 使用 Object.assign() 可以快速實現淺拷貝:
const original = { a: 1, b: { c: 2 } };
const copy = Object.assign({}, original);// 展開運算符(...)
// ES6 的展開運算符也能實現淺拷貝:
const original = { a: 1, b: { c: 2 } };
const copy = Object.assign({}, original);// 數組的淺拷貝
// 對于數組,可以使用 slice() 或 concat():
const originalArray = [1, 2, { a: 3 }];
const copyArray = originalArray.slice();
注意
引用賦值共享同一個對象,無獨立性,不屬于淺拷貝
淺拷貝第一層屬性獨立,嵌套引用類型仍共享
var a = {a:1}
var b = a
深拷貝
會遞歸復制對象的所有層級,包括引用類型屬性,生成一個完全獨立的新對象。修改深拷貝后的對象不會影響原對象。
深拷貝開辟一個新的棧,兩個對象的屬性完全相同,但是對應兩個不同的地址,修改一個對象的屬性,不會改變另外一個
利用JSON的序列化和反序列化實現深拷貝
JSON.parse(JSON.stringify())
優點:簡單易用,常見的深拷貝的方法
缺點:無法處理函數、Symbol、undefined等非 JSON 兼容類型,會丟失這些屬性
const original = { a: 1, b: { c: 2 } };
const copy = JSON.parse(JSON.stringify(original));
遞歸實現深拷貝
優點:可以處理各種類型
缺點:需要手動處理循環引用等問題
function deepClone(obj) {if (obj === null || typeof obj !== 'object') {return obj;}const clone = Array.isArray(obj) ? [] : {};for (let key in obj) {if (obj.hasOwnProperty(key)) {clone[key] = deepClone(obj[key]);}}return clone;
}
第三方庫lodash的cloneDeep
優點:功能完善,處理了各種邊界情況
缺點:需要引入額外庫
const _ = require('lodash');
const obj = {a: 1, b: {c: 2}};
const clone = _.cloneDeep(obj);
函數緩存的概念
函數緩存是一種優化技術,通過存儲函數計算結果避免重復執行相同輸入的計算。適用于計算成本高或輸入輸出穩定的場景,如遞歸、API調用或數學運算。
函數緩存,就是將函數運算過的結果進行緩存,本質上就是用空間(緩存存儲)換時間(計算過程),常用于緩存數據計算結果和緩存對象
?實現方法
實現函數緩存主要依靠閉包、柯里化、高階函數。詳解在其他文章。