一、資料型別存盤
-
在JavaScript中存在兩大資料型別:基本型別、參考型別,
-
基本資料型別存放在堆疊中,是一段簡單的資料段,資料大小確定,記憶體空間大小可以分配,是直接按值存放的,可以按值訪問,
-
參考資料型別存放在堆中,變數在堆疊中保存的是指向堆記憶體的地址值,這個地址值指向對應的物件型別,訪問堆記憶體中的物件是通過地址值訪問的,

-
二、淺拷貝
-
淺拷貝,指的是創建新的資料,這個資料有著原始資料屬性值的一份精確拷貝,
-
如果屬性是基本型別,拷貝的就是基本型別的值,如果屬性是參考型別,拷貝的就是記憶體地址,
-
即淺拷貝是拷貝一層,
-
下面簡單實作一個淺拷貝:
function shallowClone (obj) { const newObj = {} for (let prop in obj) { if (obj.hasOwnProperty(prop)) { newObj[prop] = obj[prop] } } return newObj } -
在JavaScript中,存在淺拷貝的現象有:
Object.assign()Array.prototype.slice()Array.prototype.concat()使用擴展運算子實作的復制
-
Object.assign()
var obj = { age: 18, nature: ['smart', 'good'], names: { name1: 'fx', name2: 'xka' }, love: function () { console.log('fx is a great girl') } } var newObj = Object.assign({}, fxObj) -
slice()
const fxArr = ['One', 'Two', 'Three'] const fxArrs = fxArr.slice(0) fxArrs[1] = 'love' consloe.log(fxArr) // ['One', 'Two', 'Three'] consloe.log(fxArrs) // ['One', 'love', 'Three'] -
concat()
const fxArr = ['One', 'Two', 'Three'] const fxArrs = fxArr.concat() fxArrs[1] = 'love' consloe.log(fxArr) // ['One', 'Two', 'Three'] consloe.log(fxArrs) // ['One', 'love', 'Three'] -
擴展運算子
const fxArr = ['One', 'Two', 'Three'] const fxArrs = [...fxArr] fxArrs[1] = 'love' consloe.log(fxArr) // ['One', 'Two', 'Three'] consloe.log(fxArrs) // ['One', 'love', 'Three']
三、深拷貝
-
深拷貝開辟一個新的堆疊,兩個物件相同,但是對應兩個不同的地址,修改一個物件的屬性,不會改變另一個物件的屬性,
-
常見的深拷貝方式有:
_.cloneDeep()jQuery.extend()JSON.stringify()回圈遞回
-
_.cloneDeep()
const _ = require('lodash') const obj1 = { a: 1, b: { f: { g: 1 } }, c: { 1, 2, 3 } } const obj2 = _.cloneDeep(obj1) console.log(obj1.b.f === obj2.b.f) // false -
jQuery.extend()
const $ = require('jquery') const obj1 = { a: 1, b: { f: { g: 1 } }, c: { 1, 2, 3 } } const obj2 = $.extend(true, {}, obj1) console.log(obj1.b.f === obj2.b.f) // false -
JSON.stringify()
const obj = { name: 'A', name1: 'undefined', name2: function () {}, name3: Symbol('A') } const obj2 = JSON.parse(JSON.stringify(obj1)) // 會忽略undefined、Symbol、函式 console.log(obj2) // { name: 'A' } -
回圈遞回
function deepClone (obj, hash = new WeakMap()) { if (obj === null) return obj // 如果是null或者undefined,就不進行拷貝操作 if (obj instanceof Date) return new Date(obj) if (obj instanceof RegExp) return new RegExp(obj) // 可能是物件或者普通的值,如果是函式的話不需要深拷貝 if (typeof obj !== 'Object') return obj // 如果是物件,就進行深拷貝 if (hash.get(obj)) return hash.get(obj) let cloneObj = new obj.constructor() // 找到的是所屬型別原型上的constructor,而原型上的constructor指向的是當前類本身 hash.set(obj, cloneObj) for (let key in obj) { if (obj.hasOwnProperty(key)) { // 實作一個遞回拷貝 cloneObj[key] = deepClone(obj[key], hash) } } return cloneObj }
四、區別
-
淺拷貝只復制記憶體地址,而不復制物件本身,新舊物件還是共享同一塊記憶體,修改物件屬性會影響原物件,
// 淺拷貝 const obj1 = { name: 'init', arr: [1, [2, 3], 4] } const obj3 = shallowClone(obj1) // 一個淺拷貝方法 obj3.name = 'update‘ obj3.arr[1] = [5, 6, 7] // 新舊物件還是共享同一塊記憶體 console.log('obj1', obj1) // obj1 { name: 'init', arr: [1, [5, 6, 7], 4] } console.log('obj3', obj3) // obj3 { name: 'update', arr: [1, [5, 6, 7], 4] } -
深拷貝會另外創造一個一模一樣的物件,新物件與原物件不共享記憶體,修改新物件不會改到原物件,
// 深拷貝 const obj1 = { name: 'init', arr: [1, [2, 3], 4] } const obj4 = deepClone(obj1) // 一個深拷貝方法 obj4.name = 'update‘ obj4.arr[1] = [5, 6, 7] // 新物件與原物件不共享記憶體 console.log('obj1', obj1) // obj1 { name: 'init', arr: [1, [2, 3], 4] } console.log('obj4', obj4) // obj4 { name: 'update', arr: [1, [5, 6, 7], 4] } -
當拷貝型別為參考型別時:
- 淺拷貝是拷貝一層,屬性為物件時,淺拷貝是復制,兩個物件指向同一個地址,
- 深拷貝是遞回拷貝深層次,屬性為物件時,深拷貝是新開堆疊,兩個物件指向不同的地址,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/538475.html
標籤:其他
上一篇:ES6
下一篇:事件物件的兼容
