JS深拷貝
JS中拷貝對象可以按照拷貝的程度可以分為淺拷貝和深拷貝,有些時候我們需要拷貝之后的對象和拷貝之前的對象解耦,即脫離聯(lián)系,也就是改變其中一者,另一者不會變化,典型的場景有:狀態(tài)的回溯。如果我們對狀態(tài)對象使用淺拷貝,則無法對狀態(tài)進(jìn)行回溯,但如果使用深拷貝,則可以很容易的對狀態(tài)進(jìn)行回溯和跟蹤。實現(xiàn)深拷貝,主要由以下兩種方式:(值得一提的是,JS原生數(shù)組中的 concat、slice 方法還有 Object.assign 方法都是一層拷貝,即淺拷貝)
- JSON (缺點:無法拷貝函數(shù))
function copy(o) {
return JSON.parse(JSON.stringify(o))
}
- 遞歸實現(xiàn)
var deepCopy = function(obj) {
if (typeof obj !== 'object') return obj
var newObj = (Object.prototype.toString.call(obj) === '[object Array]') ? [] : {}
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = (typeof obj[key] !== 'object') ? obj[key]: deepCopy(obj[key])
}
}
return newObj
}
instanceof
instanceof 是用來判斷對象是是某類的實例,或者是否是某類的子類的實例,它的實現(xiàn)原理可以是下面這樣,L 表示實例,R 表示某類。
function instanceOf(L, R) {
R = R.prototype
L = L.__proto__
while (true){
if (L === null)
return false
if (R === L)
return true
L = L.__proto__
}
}
判斷是否為數(shù)組
JS中數(shù)組也屬于對象,所以無法通過 typeof 直接判斷,這個時候就得采用其他方式,主要有一下幾種方式:
- 使用 instanceof
var arr = []
console.log(arr instanceof Array)
- 使用 constructor
var arr = []
console.log(arr.constructor === Array)
- 判斷對象是否有 push 等數(shù)組的一些方法
var arr = []
console.log(!!arr.push && !!arr.concat)
- 使用對象的 toString
var arr = []
console.log(Object.prototype.toString.call(arr) === '[object Array]')
- 使用 ES5 中的 Array.isArray 方法
var arr = []
console.log(Array.isArray(arr))
方法 1-3 有兼容性問題,方法 5 可能不兼容老款瀏覽器,所以最好使用方法 4