Open diveDylan opened 4 years ago
预备工作 我们需要科隆的对象可能有Array,Object,Date, Reg,因此我们需要判断四类对象,常用的判断对象方法有三种 typeof, instanceof,toString
Array
Object
Date
Reg
typeof
instanceof
toString
首先我们测试typeof,顺带复习下原知识
typeof new Date() // 'object' typeof /1/ // 'object' typeof [] // 'object' typeof {} // 'object' typeof null // 'object' typeof 1 // 'number' typeof '1' // 'string' typeof undefined // 'undefined'
因为无法区分RegExp,Date,Array数据格式,所以typeof的方法不可取
RegExp
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上
通俗的理解可以认为检测A是否为B的实例
1 instance Number // false new Number(1) instanceof Number // true Number(1) instanceof Number // false '1' instanceof String // false new String(1) instanceof String // true String(1) instanceof String // false [] instanceof Array // true [] instanceof Object // true /3/ instanceof RegExp // true /3/ instanceof Object // true {} instanceof Object // SyntaxError const a = {} a instanceof Object // true new Date() instanceof Date // true new Date() instanceof Object // true
因为Date和RegExp等本质也是对象所以无法区分,该方法也不适用
toStirng的判断方法主要还是利用Object.prototype.toString.call(this)的方法,该方法返回 "[object type]"
toStirng
Object.prototype.toString.call(this)
const getType = obj => Object.prototype.toString.call(obj) getType(1) // "[object Number]" getType('1') // "[object String]" getType(undefined) // "[object Undefined]" getType(null) // "[object Null]" getType([]) // "[object Array]" getType(/1/) // "[object RegExp]" getType(new Date()) // "[object Date]" getType({}) // "[object Object]" getType(true) // "[object Boolean]"
toString的表现堪称完美。
如果不考虑原型按照我们上面的测试代码应该是这样的
const types = { OBJECT: '[object Object]', ARRAY: '[object Array]', DATE: '[object Date]', REGEXP: '[object RegExp]' } const toStr = obj => Object.prototype.toString.call(obj) const isType = (obj, typeName) => toStr(obj) === types[typeName] function deepClone(obj) { if (isType(obj, 'OBJECT')) { const objCopy = {} Object .keys(obj) .forEach(key => { objCopy[key] = deepClone(obj[key]) }) return objCopy } if (isType(obj, 'ARRAY')) { return obj.map(key => deepClone(key)) } if (isType(obj, 'Date')) { return new Date(date.getTime()) } if (isType(obj, 'REGEXP')) { return new RegExp(obj) } return obj // 其他类型直接赋值即可 }
为什么要clone原型?因为对象很可能是一个实例,我们举一个列子
class Person { constructor() { this.name = 'dylan' } say() { console.log('hello world') } }
deepClone实例后你可能发现下图所示的现象 其实解决起来也相当简单,进行原型赋值,就跟继承一样
deepClone
const types = { OBJECT: '[object Object]', ARRAY: '[object Array]', DATE: '[object Date]', REGEXP: '[object RegExp]' } const isOriginObject = obj => obj.__proto__.constructor === Object const toStr = obj => Object.prototype.toString.call(obj) const isType = (obj, typeName) => toStr(obj) === types[typeName] function deepClone(obj) { if (isType(obj, 'OBJECT')) { let objCopy if (!isOriginObject(obj)) { objCopy = Object.create(null) objCopy.__proto__ = Object.create(obj.__proto__.constructor.prototype) } else { objCopy = {} } Object .keys(obj) .forEach(key => { objCopy[key] = deepClone(obj[key]) }) return objCopy } if (isType(obj, 'ARRAY')) { return obj.map(key => deepClone(key)) } if (isType(obj, 'Date')) { return new Date(date.getTime()) } if (isType(obj, 'REGEXP')) { return new RegExp(obj) } return obj }
预备工作 我们需要科隆的对象可能有
Array
,Object
,Date
,Reg
,因此我们需要判断四类对象,常用的判断对象方法有三种typeof
,instanceof
,toString
typeof
首先我们测试typeof,顺带复习下原知识
因为无法区分
RegExp
,Date
,Array
数据格式,所以typeof
的方法不可取instanceof
通俗的理解可以认为检测A是否为B的实例
因为
Date
和RegExp
等本质也是对象所以无法区分,该方法也不适用toString
toStirng
的判断方法主要还是利用Object.prototype.toString.call(this)
的方法,该方法返回 "[object type]"toString
的表现堪称完美。clone without propoperty
如果不考虑原型按照我们上面的测试代码应该是这样的
clone property
为什么要clone原型?因为对象很可能是一个实例,我们举一个列子
deepClone
实例后你可能发现下图所示的现象 其实解决起来也相当简单,进行原型赋值,就跟继承一样