zoukankan      html  css  js  c++  java
  • 如何深度复制一个javascript对象

    前言

    最近有人问我,如何将一个对象复制一份,因为他遇到了一个需求,需要将后端获取的数据,保存一份,原始数据会因为交互而发生变化,最终需要对比两份数据的异同。
    他是一个刚入行的小朋友,他的实现方式就是新声明了一个变量,然后将数据赋值给了变量。本以为这就ok了,结果修改原数据,复制出来的变量中的内容,依然发生了变化。
    在此,整理一下。(大中小)牛略过,仅为帮助新人,聊以解忧。

     

    知识铺垫,值类型,与引用类型

    我们用一个新的概念来理解这两种类型,连锁店连锁店的钥匙

    1. 类型包含如下:number,string,boolean,undefind,null;

        变量的交换如同新开了一家连锁店,店面统一,但实际上新店与旧点之间,互无影响,各自运营,独立结算。 

     

    var flagship  = 'xx连锁店'; //当前为旗舰店
    var shop1 = flagship;      //第一家连锁店
    var shop2 = flagship;      //第二家连锁店

     

    2. 引用类型包含如下:对象,数组,函数

        变量的交换等于现有一家店面的钥匙(变量地址引用)复制给了另外一个老板,此时两个人共同管理一家门店,两个人的行为都可能对着一间门店的运营造成影响。

    var boss1 = {shop:'xx连锁店','state':'开业中'}
    var boss2 = boss1;//复制了一把钥匙给boss2
    boss2.state = '装修中'; //boss2将门店升级改造,暂时停业
    console.log(boss1.state) // 装修中 

    由此可见,对应用类型的变量仅仅通过变量赋值,无法达到深拷贝的意图,仅仅只是浅拷贝。

    如何去做呢

    以下简单实现一个对纯数据对象(JSON)的深拷贝

    1.实现值类型的复制:

    从上面我们知道,值类型可以简单的通过变量赋值来实现深拷贝,所以先完成如下代码:

    function clone(item) {
      var type = typeof item, 
         baseTypes = ['boolean','number','string','undefined'],
         result;   
    //使用typeof 可以准确判断出 boolean string number undefined   //null 使用全等方式进行判断   if(baseTypes.indexOf(type) >= 0 || item === null){      result = item;   }
      return result; }

    2.实现引用类型中数组的复制:

    首先需要判断是否为数组,其次将数组进行遍历,分别复制数组中的内容,暂时不考虑数组中元素包含引用类型

    function clone(item) {
      var result;
      //判断当前元素是否为数组,至于为什么这么判断,不深入了,有兴趣自己百度吧~
      if(Object.prototype.toString.call(item) === "[object Array]"){
        result = [];
        //循环数组,将数组内容放到新数组中(未考虑数组中元素是否包含引用类型)
        item.forEach(function (i) {
          result.push(i);
        })
      }
      return result;
    }

    3.实现引用类型中对象的复制:

    首先需要判断是否为对象,其次将对象进行遍历,分别复制对象中的内容,暂时不考虑数组中元素包含引用类型

    function clone1(item) {
      var result;
      //判断当前元素是否为对象,至于为什么这么判断,不深入了,有兴趣自己百度吧~
      if(Object.prototype.toString.call(item) === "[object Object]"){
        result = {};
        //遍历对象,将对象中内容放到新对象中(未考虑对象中元素是否包含引用类型)
        for(var i in item){
          result[i] = item[i]; 
        }
      }
      return result;
    }

    4.将对象或数组中包含引用类型值的情况考虑进去,一个简单的递归调用,整体代码如下

    function clone(item) {
      var type = typeof item,
        baseTypes = ['boolean','number','string','undefined'],
        result;
      //使用typeof 可以准确判断出 boolean string number undefined
      //null 使用全等方式进行判断
      if(baseTypes.indexOf(type) >= 0 || item === null){
        result = item;
      }else if(Object.prototype.toString.call(item) === "[object Array]"){ // 判断是否为数组
        result = [];
        //循环数组,将数组内容放到新数组中
        item.forEach(function (i) {
          result.push(clone(i));
        })
      }else if(Object.prototype.toString.call(item) === "[object Object]"){ // 判断是否为对象
        result = {};
        //遍历对象,将对象中内容放到新对象中(未考虑对象中元素是否包含引用类型)
        for(var i in item){
          result[i] = clone(item[i]);
        }
      }else{
        result = item;
      }
        return result;
    }

    PS:还有没有其他简便方法呢

    我们知道JSON,本身提供两个方法 JSON.stringify() 和 JSON.parse(),提供了将JSON对象转换为JSON结构的字符串,以及将JSON结构的字符串换换为JSON

    so:简便方法来了

    function clone(item) {
      var jsonStr = JSON.stringify(item);
      return JSON.parse(jsonStr);
    }
  • 相关阅读:
    CSU 1333 Funny Car Racing
    FZU 2195 检查站点
    FZU 2193 So Hard
    ZOJ 1655 FZU 1125 Transport Goods
    zoj 2750 Idiomatic Phrases Game
    hdu 1874 畅通工程续
    hdu 2489 Minimal Ratio Tree
    hdu 3398 String
    洛谷 P2158 [SDOI2008]仪仗队 解题报告
    POJ 1958 Strange Towers of Hanoi 解题报告
  • 原文地址:https://www.cnblogs.com/chenqf/p/7891048.html
Copyright © 2011-2022 走看看