JavaScript 深层克隆对象详解及实例_javascript技巧

 JavaScript 深层克隆对象

今天做项目,有个需求需要用到深层克隆对象,并且要求在原型链上编程 于是心血来潮索性来复习一下这个知识点,在网上找了相应的知识,

克隆对象,这名词看着高大上,其实也没什么,便是拷贝一个长的一模一样的对象
也许有初学的小伙伴在想,那还不简单么,so easy

var obj1 = {name: 'payen'};

var obj2 = obj1;

这可并不是克隆对象,obj1和obj2根本就是同一个对象,

他俩指向同一个内存地址空间,拿到了同样的一个小房子

这是应为对象是引用值

说到引用值

JavaScript中引用值只有对象

这里注意,数组是特殊的对象,函数也是特殊的可执行对象, 也就是说,它们也是对象 ,所谓深层克隆对象就是说它并不想要同样的房子,房子你也要给我复制一份一模一样的 不知道我这么说大家能不能理解= ̄ω ̄= ,也就是深层克隆对象引用值要拷贝,而相对的浅层克隆对象只要把那个引用值拿过来就好了 ,不明白不要紧,看完代码就理解了

首先来一起看看浅层克隆对象吧

var house = {
  name: 'payen',
  people: {
    father: true,
    mother: true
  }
}
function easyClone(obj){
  var newObj = {};
  for(var prop in obj){
    if(obj.hasOwnProperty(prop)){
      newObj[prop] = obj[prop];
    }
  }
  return newObj;
}
var newHouse = easyClone(house);

不要吐槽我用easy,一时想不起来“浅”英文咋说来着(真不知道我英语六级怎么过的) 。关于那个for-in有一个小性能问题,感兴趣的童鞋可以看看我的另一篇文章

这段代码很简单我就不多解释了

来看看chrome控制台

看样子很棒的样子

那么我现在做一件事

给新房子加一个人

看来这个”新房子”并不新啊,不要被变量名字迷惑了所以,有引用值出现,浅层克隆并不好用了

既然如此,我们怎么办呢

既然要得到新的对象,我们创建一个新对象,把旧对象内部的东西,再拷贝到新对象不就得了

还有一个问题如果对象里还有对象呢

那么就继续重复创建添加的过程,很显然是一个循环的过程

不过循环有两种

迭代

递归

毫无疑问递归更胜一筹

在递归循环中,遇到满足终止条件的条件时逐层返回来结束 ,那么我们就可以通过递归逐层查找引用值,直到没有引用值为止
还是看代码吧

var house = {
  name: 'payen',
  people: {
    father: true,
    mother: true,
    child: {
      age: 1
    }
  },
  money: [1000,2000,3000]
}
function deepClone(original, target){
  var target = target || {};// 如果target为undefined或没传参,设置空对象
  for(var prop in original){// 遍历原对象
    if(original.hasOwnProperty(prop)){// 只拷贝对象内部,不考虑原型链
      if(typeof original[prop] === 'object'){// 引用值
        if(Object.prototype.toString.call(original[prop]) === '[object Array]'){
          target[prop] = [];// 处理数组引用值
        }else{
          target[prop] = {};// 处理对象引用值
        }// 可以用三目运算符
        deepClone(original[prop],target[prop]);// 递归克隆
      }else{// 基本值
        target[prop] = original[prop];
      }
    }
  }
  return target;
}
var newHouse = deepClone(house);

上面写了那个if-else挺适合用三目运算符的,不过我感觉太冗长了,强迫症表示看了很不舒服 ,为了证明它真的深层克隆了,我特意把原始房子变复杂了 ,(我们不考虑函数的深层克隆,麻烦并且意义不大) ,这回它真的是新房子了

我就不展开了

可以看出来在新对象的引用值改动,旧对象并没有变

在原型链上编程同理

var house = {
  name: 'payen',
  people: {
    father: true,
    mother: true,
    child: {
      age: 1
    }
  },
  money: [1000,2000,3000]
}
Object.prototype.cloneTo = function(obj){
  var obj = obj || {};
  for(var prop in this){
    if(this.hasOwnProperty(prop)){
      if(typeof this[prop] === 'object'){
        if(Object.prototype.toString.call(this[prop]) === '[object Array]'){
          obj[prop] = [];
        }else{
          obj[prop] = {};
        }
        this[prop].cloneTo(obj[prop]);
      }else{
        obj[prop] = this[prop];
      }
    }
  }
  return obj;
}
var newHouse = {};
house.cloneTo(newHouse);

感谢阅读,希望能帮到大家,谢谢大家对本站的支持!

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索js
深层克隆对象
深层恐惧电影详解、javascript深度克隆、javascript克隆对象、javascript 数组克隆、javascript 克隆,以便于您获取更多的相关知识。

时间: 2024-10-30 20:18:23

JavaScript 深层克隆对象详解及实例_javascript技巧的相关文章

JavaScript定时器详解及实例_javascript技巧

JS里设定延时: 使用SetInterval和设定延时函数setTimeout 很类似.setTimeout 运用在延迟一段时间,再进行某项操作. setTimeout("function",time) 设置一个超时对象 setInterval("function",time) 设置一个超时对象 SetInterval为自动重复,setTimeout不会重复. clearTimeout(对象) 清除已设置的setTimeout对象 clearInterval(对象)

jQuery.extend()的实现方式详解及实例_javascript技巧

复制代码 代码如下: <script type="text/javascript" src="jquery-1.5.2.js"></script><script>obj1 = { a : 'a', b : 'b' };obj2 = {  x : { xxx : 'xxx', yyy : 'yyy' },  y : 'y' }; $.extend(true, obj1, obj2); alert(obj1.x.xxx);  // 得

JavaScript的document对象详解

javascript|对象|详解 1.对象属性document.title //设置文档标题等价于HTML的<title>标签document.bgColor //设置页面背景色document.fgColor //设置前景色(文本颜色)document.linkColor //未点击过的链接颜色document.alinkColor //激活链接(焦点在此链接上)的颜色document.vlinkColor //已点击过的链接颜色document.URL //设置URL属性从而在同一窗口打开

Javascript中call,apply,bind方法的详解与总结_javascript技巧

以下内容会分为如下小节: 1.call/apply/bind方法的来源 2.Function.prototype.call() 3.Function.prototype.apply() 3.1:找出数组中的最大数 3.2:将数组的空元素变为undefined 3.3:转换类似数组的对象 4.Function.prototype.bind() 5.绑定回调函数的对象 6.call,apply,bind方法的联系和区别 1.call/apply/bind方法的来源 首先,在使用call,apply,

详解Bootstrap插件_javascript技巧

在前面 布局组件 章节中所讨论到的组件仅仅是个开始.Bootstrap 自带 12 种 jQuery 插件,扩展了功能,可以给站点添加更多的互动.即使您不是一名高级的 JavaScript 开发人员,您也可以着手学习 Bootstrap 的 JavaScript 插件.利用 Bootstrap 数据 API(Bootstrap Data API),大部分的插件可以在不编写任何代码的情况被触发. 站点引用 Bootstrap 插件的方式有两种: 单独引用:使用 Bootstrap 的个别的 *.j

详解Bootstrap按钮_javascript技巧

描述 Bootstrap Button(按钮)JavaScript 插件允许您加强按钮的功能.您可以控制按钮的状态,也可以为组件创建按钮组,比如工具条. 什么是必需的 您必须引用 jquery.js 和 bootstrap-button.js - 这两个 JavaScript 文件.它们都位于 docs/assets/js 文件夹内. 如何使用它 您可以不编写任何 JavaScript 只通过标记使用该插件,也可以通过 JavaScript 启用按钮. Bootstrap 提供了一些选项来定义按

JSON对象 详解及实例代码_基础知识

前面的话 json(javascript object notation)全称是javascript对象表示法,它是一种数据交换的文本格式,而不是一种编程语言,用于读取结构化数据.2001年由Douglas Crockford提出,目的是取代繁琐笨重的XML格式.本文将详细介绍关于json的内容  语法规则 JSON的语法可以表示以下三种类型的值 [1]简单值 简单值使用与JavaScript相同的语法,可以在JSON中表示字符串.数值.布尔值和null 字符串必须使用双引号表示,不能使用单引号

javascript中document对象详解

注:页面上元 素name属性和JavaScript引用的名称必须一致包括大小写 否则会提示你一个错误信息 "引用的元素为空或者不是对象\\\\\" ----------------------- 对象属性 document.title //设置文档标题等价于HTML的title标签 document.bgColor //设置页面背景色 document.fgColor //设置前景色(文本颜色) document.linkColor //未点击过的链接颜色 document.alink

JavaScript 继承详解 第一篇_javascript技巧

面向对象与基于对象 几乎每个开发人员都有面向对象语言(比如C++.C#.Java)的开发经验. 在传统面向对象的语言中,有两个非常重要的概念 - 类和实例. 类定义了一类事物公共的行为和方法:而实例则是类的一个具体实现. 我们还知道,面向对象编程有三个重要的概念 - 封装.继承和多态. 但是在JavaScript的世界中,所有的这一切特性似乎都不存在. 因为JavaScript本身不是面向对象的语言,而是基于对象的语言. 这里面就有一些有趣的特性,比如JavaScript中所有事物都是对象, 包