原生js实现对象的克隆

简介: 原生js实现对象的克隆
   // 对象的浅克隆 作用是把一个对象克隆到另一个对象
  // 缺陷是只能克隆原始值 不能克隆引用值
  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);


20200206113031316.png


解析: 因为对象的浅克隆,克隆的都是原始值,当obj里面的属性值里面改变,obj1里面的值是不会改变的,因为原始值改变的是一个栈里面的值,而对象是引用值,两个对象引用的地址不一样,所以改变一个对象,另一个对象是不会改变的,如下图:


20200206112854545.png


**深度克隆**
// 深度克隆,解决浅克隆的缺陷 克隆对象,不管兑现里面的是原始值还是引用值,都克隆到另一个对象,
  // 并且改变一个对象里面的引用值,另一个对象还是不变,实现如下
  // 实现的思路如下:
  // 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)
结果如下:


20200206124117105.png


当我改变其中一个对象时候,另一个不会被改变,如下图:


20200206124222693.png


// 深度克隆 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!!!

相关文章
|
1月前
|
JavaScript 前端开发
JavaScript Date(日期) 对象
JavaScript Date(日期) 对象
38 2
|
5天前
|
Web App开发 JavaScript 前端开发
如何确保 Math 对象的方法在不同的 JavaScript 环境中具有一致的精度?
【10月更文挑战第29天】通过遵循标准和最佳实践、采用固定精度计算、进行全面的测试与验证、避免隐式类型转换以及持续关注和更新等方法,可以在很大程度上确保Math对象的方法在不同的JavaScript环境中具有一致的精度,从而提高代码的可靠性和可移植性。
|
1天前
|
JavaScript 前端开发
如何在 JavaScript 中使用 __proto__ 实现对象的继承?
使用`__proto__`实现对象继承时需要注意原型链的完整性和属性方法的正确继承,避免出现意外的行为和错误。同时,在现代JavaScript中,也可以使用`class`和`extends`关键字来实现更简洁和直观的继承语法,但理解基于`__proto__`的继承方式对于深入理解JavaScript的面向对象编程和原型链机制仍然具有重要意义。
|
5天前
|
JavaScript 前端开发 图形学
JavaScript 中 Math 对象常用方法
【10月更文挑战第29天】JavaScript中的Math对象提供了丰富多样的数学方法,涵盖了基本数学运算、幂运算、开方、随机数生成、极值获取以及三角函数等多个方面,为各种数学相关的计算和处理提供了强大的支持,是JavaScript编程中不可或缺的一部分。
|
29天前
|
存储 JavaScript 前端开发
JavaScript 对象的概念
JavaScript 对象的概念
35 4
|
27天前
|
缓存 JavaScript 前端开发
JavaScript中数组、对象等循环遍历的常用方法介绍(二)
JavaScript中数组、对象等循环遍历的常用方法介绍(二)
29 1
|
28天前
|
存储 JavaScript 前端开发
js中函数、方法、对象的区别
js中函数、方法、对象的区别
15 2
|
1月前
|
JavaScript 前端开发 Unix
Node.js 全局对象
10月更文挑战第5天
21 2
|
1月前
|
存储 JavaScript 前端开发
js中的对象
js中的对象
18 3
|
1月前
|
JavaScript 前端开发
JavaScript Math(算数) 对象
JavaScript Math(算数) 对象
20 4