// 对象的浅克隆 作用是把一个对象克隆到另一个对象 // 缺陷是只能克隆原始值 不能克隆引用值 function shallowClone(origin, target) { // 第一步 我们需要把对象源里面的属性克隆到目标或者数组上 var target = target || {}; for(var prop in origin){ // 防止克隆原型上的属性,我们在es5中有严格模式,但是为了写的代码更完美, // 加上这一行,克隆只能克隆该对象上面的除了原型上的属性 if(origin.hasOwnProperty(prop)){ target[prop] = origin[prop]; } } return target } var obj = { name: 'adf', age: '12', sex: 'male' } var obj1 = {}; obj1 = shallowClone(obj); console.log(obj1);
解析: 因为对象的浅克隆,克隆的都是原始值,当obj里面的属性值里面改变,obj1里面的值是不会改变的,因为原始值改变的是一个栈里面的值,而对象是引用值,两个对象引用的地址不一样,所以改变一个对象,另一个对象是不会改变的,如下图:
**深度克隆** // 深度克隆,解决浅克隆的缺陷 克隆对象,不管兑现里面的是原始值还是引用值,都克隆到另一个对象, // 并且改变一个对象里面的引用值,另一个对象还是不变,实现如下 // 实现的思路如下: // 1.遍历源对象,拿到对象的每一个属性 // 2.判断第一层的属性是否为原始值,如果是原始值则直接赋值 // 3. 不是原始值则需要判单是对象还是数组,创建对应的新的对象或者数组,保证引用值使用的是自己单独的引用地址 // 3. 递归使用deepClone 方法 function deepClone(origin, target) { // 定义三个变量, 如果不传target 则使用自己定义的 // 判断是对象和数组有三种方法: // 1. Object.prototype.toSring.call() 里面穿数组或者对象会放回不一样的字符串, 如:传入数组返回 "[object, Array]" // 2. A instanceof B 使用这个比比较的是 A的原型链上是否有B的原型 数组和对象两者本身都是对象类型名单上原型链上是不同的 // 3. 使用constructor 对比的也是原型里面的构造器 var target = target || {} , toStr = Object.prototype.toString, isArray = "[object, Array]"; for(var prop in origin){ if (origin.hasOwnProperty(prop)) { // 因为typeof null = 'object' 所以此处需要判断是否为引用值 if (origin[prop] !== "null" && typeof(origin[prop]) == "object") { // 判断当前的引用值是否为数组 target[prop] = (toStr.call(origin[prop] == isArray)) ? [] : {}; // 递归 deepClone(origin[prop], target[prop]); }else{ target[prop] = origin[prop]; } } } return target; } var deepObj = { name: 'avc', age: 12, card: ['master', 'visa'], son: { name: 'erw', son: { name: 'test' } } }; var cloneObj = deepClone(deepObj); console.log(cloneObj) 结果如下:
当我改变其中一个对象时候,另一个不会被改变,如下图:
// 深度克隆 es6写法
/** * 克隆的方法 * @param obj * @returns {*} */ export function cloneValue(obj) { if (obj instanceof Array ) { return cloneArray(obj); } else if (obj instanceof Object) { return cloneObj(obj) } else { return obj; } } /** * 克隆对象 * @param obj * @returns {{}} */ function cloneObj(obj) { let res = {}; // 获取对象里面的所有属性,包括对象里面的属性 let objAttr = Object.getOwnPropertyNames(obj); for (let i = 0; i < objAttr.length; i++) { res[objAttr[i]] = cloneValue(obj[objAttr[i]]); } return res; } /** * 克隆数组 * @param array * @returns {[]} */ function cloneArray(array) { let arr = new Array(array.length); for (let i = 0; i < array.length; i++) { arr[i] = cloneValue(array[i]); } return arr; }
以上代码是博主个人学习用的时候写出来的,如果存在bug, 还望见谅, more interest, less interests!!!