JS实现深拷贝、instanceof、判断是否为数组

JS深拷贝

JS中拷贝对象可以按照拷贝的程度可以分为浅拷贝和深拷贝,有些时候我们需要拷贝之后的对象和拷贝之前的对象解耦,即脱离联系,也就是改变其中一者,另一者不会变化,典型的场景有:状态的回溯。如果我们对状态对象使用浅拷贝,则无法对状态进行回溯,但如果使用深拷贝,则可以很容易的对状态进行回溯和跟踪。实现深拷贝,主要由以下两种方式:(值得一提的是,JS原生数组中的 concat、slice 方法还有 Object.assign 方法都是一层拷贝,即浅拷贝)

  1. JSON (缺点:无法拷贝函数)
function copy(o) {
    return JSON.parse(JSON.stringify(o))
}
  1. 递归实现
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 是用来判断对象是是某类的实例,或者是否是某类的子类的实例,它的实现原理可以是下面这样,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__
    }
}

判断是否为数组

JS中数组也属于对象,所以无法通过 typeof 直接判断,这个时候就得采用其他方式,主要有一下几种方式:

  1. 使用 instanceof
var arr = []
console.log(arr instanceof Array)
  1. 使用 constructor
var arr = []
console.log(arr.constructor === Array)
  1. 判断对象是否有 push 等数组的一些方法
var arr = []
console.log(!!arr.push && !!arr.concat)
  1. 使用对象的 toString
var arr = []
console.log(Object.prototype.toString.call(arr) === '[object Array]')
  1. 使用 ES5 中的 Array.isArray 方法
var arr = []
console.log(Array.isArray(arr))

方法 1-3 有兼容性问题,方法 5 可能不兼容老款浏览器,所以最好使用方法 4

推荐阅读更多精彩内容

  • pdf下载地址:Java面试宝典 第一章内容介绍 20 第二章JavaSE基础 21 一、Java面向对象 21 ...
    王震阳阅读 77,208评论 25 509
  • ES6 http://es6.ruanyifeng.com 目录 1 let 和 const 命令 2 变量的解构...
    常青1890阅读 5,659评论 0 41
  • 0. 写在前面 当你开始工作时,你不是在给你自己写代码,而是为后来人写代码。 —— Nichloas C. Zak...
    康斌阅读 3,191评论 0 39
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 4,166评论 1 15
  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 12,583评论 7 166