JS的基本數據類型
- 基本數據類型:String,Boolean,Number,Undefined,Null;
- 引用數據類型:Object(Array,Date,RegExp,Function);
淺拷貝
- 淺拷貝是會將對象的每個屬性進行依次復制,但是當對象的屬性值是引用類型時,實質復制的是其引用,當引用指向的值改變時也會跟着變化。
Object.assign
、 擴展運算符...
、Array.prototype.slice()
、Array.prototype.concat()
等
深拷貝
- 深拷貝復制變量值,對於引用數據,則遞歸至基本類型后,再復制。
- 深拷貝后的對象與原來的對象是完全隔離的,互不影響,對一個對象的修改並不會影響另一個對象
示例:
let obj = { name : 'Michael', age : 18 , others : { hobbies : ['basketball','gambling'], team : 'Bulls', }, } let [newObj,newObj2] = [Object.assign({},obj),{...obj}] obj.name = 'Kobe'; obj.others.team = 'Lakers'; console.log(obj)
console.log(newObj)
console.log(newObj2)
我們能看出:
- newObj及newObj2的others為引用數據類型,因此與原對象obj的屬性值指向同一塊內存地址,修改原對象的others內的內容,新對象的內容也會更改
- 第一層的屬性值為基本數據類型(String),修改原對象,對新對象不造成影響
因此 深拷貝與淺拷貝的區別為
-
淺拷貝當第一層的屬性值是基本數據類型時,新的對象和原對象互不影響,但是如果第一層的屬性值是引用數據類型時,那么新對象和原對象的屬性值其指向的是同一塊內存地址。
- 深拷貝會另外創造一個一模一樣的對象,新對象跟原對象不共享內存,修改新對象不會改到原對象;
深拷貝的代碼實現
- 如果是基本數據類型,直接返回
- 如果是復雜數據類型,遞歸。
- 如果是
RegExp
或者Date
類型,返回對應類型
let obj = { name: 'Michael', age: 18, others: { hobbies: ['basketball', 'gambling'], team: 'Bulls', }, } // 遞歸拷貝 function deepClone(obj) { if (obj instanceof RegExp) return new RegExp(obj); if (obj instanceof Date) return new Date(obj); if (obj === null || typeof obj !== 'object') return obj //如果不是引用類型則直接返回 let newObj = new obj.constructor(); //如果obj是數組,newObj=[];如果obj是對象,newObj={} for (let key in obj) { if (obj.hasOwnProperty(key)) { //是否是自身的對象 newObj[key] = deepClone(obj[key]) //賦值 } } return newObj } const copyObj = deepClone(obj); obj.others.team = 'Lakers'; console.log(obj,copyObj)
經比較:深拷貝后修改原對象的值並不會改變新對象的值