前言

本篇适合前端新人,下面开始......

对于前端新手来说(比如博主),每当对js的对象做操作时,都是一种痛苦,原因就是在于对象的赋值是引用的传递,并非值的传递,虽然看上去后者赋值给了前者,他们就各奔东西了,但是他们却紧紧相连,为了解决这一问题,我们需要从根源上来切断对象赋值时就对象与新对象之间的藕断丝连......

拷贝

我们寻找方法时候,找到了拷贝这个方法,就是把要赋值的对象的属性一个一个加到新对象中去,所以我们得到了clone方法:

function clone (obj) {
  var news = {}
  for (var key in obj) {
    news[key] = obj[key]
  }
  return news
}

但是新问题又来了,我的新对象并不是空的,我的新对象还有其他属性,以上这个方法并不适用了,怎么办......

继承

对于继承这个名词,大家并不陌生,该有的留下,该继承的加进来,该覆盖的覆盖掉。于是我们稍微修改了一下上面的代码,得到了extend方法:

function extend(target, obj) {

  for (var key in obj) {
    target[key] = obj[key]
  }
  return target
}

我们把目标对象穿进去,把继承对象中的属性依依加到目标对象。最后,我们返回目标对象,虽然不比这么做目标对象已经改变,不过我们还是这样做吧。

深拷贝

问题总是不断的发现,现在我们又有问题了,我们在继承过程中,如果某一个属性值是一个对象,那么我们的继承函数仍然有引用传递,这样一来仍然联系不断!怎么办呢?这时候大牛们变引发了深拷贝这个名词,顾名思义,如果对象中还有对象,那么一层一层的拷贝下去吧,不信你能有10086层对象嵌套。

深拷贝的核心是递归继承,碰到属性值为对象,就触发递归继承。在这里,你可能想到了jQuery等功能库,的确,他们都有extend方法来实现深拷贝,但我觉得不完美,因为我们需要依靠自己的力量,不能仅仅依赖别人,因此我们又需要继续探索.....

JSON的妙用

在我们探索如果深拷贝时,JSON对象缺在偷偷地笑,我问他在笑什么,他跟我说了这样的话:

  

var obj1 = {
  name: 'xu',
  age: 21,  native: {    weight: 70,    height: 170  }
  ... //许多属性
}

var obj2 = clone(obj1) //    浅拷贝,未断开联系

var obj2 = JSON.parse(JSON.stringify(obj1))  // 深拷贝,成功断开

他告诉我说:你的clone是不行滴,我给你两个方法,分分钟让对象断子绝孙。于是,我就学会了这样进行深拷贝。但是需求还是远远不够,在现实项目中,我们需要的是在继承中深拷贝,于是我们继续探索,终于......

function deepExtend (target, obj) {
  var clone
  for (var key in obj) {
    clone = obj[key]
    if (typeof clone === 'object') {   // 只考虑数组和对象两种情况
      target[key] = JSON.parse(JSON.stringify(clone))
    } else {
      target[key] = clone
    }
  }
  return target
}

好吧,我们写出了上面这个简单的继承,不过感觉很瑕疵,万一我们需要给目标对象继承多个对象怎么办?我们如何控制是否深拷贝?低版本浏览器ie678中JSON无效怎么办?好吧,不要问了,容我再想想。

最终的继承

为了解决一系列的问题,最终我给出了一下继承方法,此继承方法类似于jQuery.extend,实际也差不多,不过相比简单易懂(个人觉得),因为加了大量汉语注释,适合新手们。

function extend () {
  //  arguments种类
  //  [deep]  可选,标注是否为深度继承
  //  target  第一个对象,则为目标对像
  //  options  之后的对象,都视为继承对象
  var args = arguments,
    target = args[0],   //  假设第一个参数为目标对象
    len = args.length,  //  获取参数总长度
    i = 1,              //  假设继承对象从下标为1开始
    deep = false,       //  初始化为浅拷贝
    tar, source, option, key
  //  如果第一个参数是布尔值,那么第二个参数做为目标对象
  if (typeof target === 'boolean') {
    deep = target
    target = args[i++]
  }
  //  遍历继承对象,并将每一个都继承到目标对象中
  for (; i < len; i++) {

    option = args[i]

    for (key in option) {
      tar = target[key]
      source = option[key]
      //  如果为深拷贝并且此时的属性值为对象,则进行递归拷贝
      if (deep && typeof source === 'object') {
        if (!tar) {   //  如果目标对象没有此属性,那么创建它
          tar = Object.prototype.call(source) === '[object Array]'? []: {}
        }
        //  将递归拷贝的结果赋值给目标对象
        target[key] = assign(deep, tar, source)
      } else{
        //  如果为浅拷贝,直接赋值
        target[key] = source
      }
    }
  }
  return target
}

最后的结尾

很遗憾本菜只能有这些本事了, 帖子内容不少,大多是废话,新人可以看一下,如果觉得有帮助,就点个赞吧~~~~

javascript中的继承与深度拷贝的更多相关文章

  1. JavaScript学习13 JavaScript中的继承

    JavaScript学习13 JavaScript中的继承 继承第一种方式:对象冒充 <script type="text/javascript"> //继承第一种方式 ...

  2. 浅谈JavaScript中的继承

    引言 在JavaScript中,实现继承的主要方式是通过原型链技术.这一篇文章我们就通过介绍JavaScript中实现继承的几种方式来慢慢领会JavaScript中继承实现的点点滴滴. 原型链介绍 原 ...

  3. JavaScript中的继承(原型链)

    一.原型链 ECMAScript中将原型链作为实现继承的主要方法,基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法. 实例1: function SupType() { this.pro ...

  4. javascript 中的继承实现, call,apply,prototype,构造函数

    javascript中继承可以通过call.apply.protoperty实现 1.call call的含义: foo.call(thisObject, args...) 表示函数foo调用的时候, ...

  5. javascript中的继承实现

    javascript虽然是一门面向对象的语言,但是它的继承机制从一开始设计的时候就不同于传统的其他面向对象语言,是基于原型的继承机制,但是在这种机制下,继承依然有一些不同的实现方式. 方法一:类式继承 ...

  6. javascript中的继承方法

    从Javascript面向对象编程(二):构造函数的继承这里,可以看到详细的说明. 我只是将其中的例子做成html文件,便于调试罢了. 1. 构造函数绑定 <html> <head& ...

  7. JavaScript 中的继承(读书笔记思维导图)

    继承是 OO 语言中的一个最为人津津乐道的概念.许多 OO 语言都支持两种继承方式:接口继承和实现继承.接口继承只继承方法签名,而实现继承则继承实际的方法.由于函数没有签名,在 ECMAScript ...

  8. javascript中关于继承的理解

    首先,你要理解在javascript中,每当一个新函数创建时,都会生成一个prototype属性,我们管它叫做原型对象.看一个例子: function foo(){ this.name='qiangq ...

  9. javascript中的继承用法

    本文实例汇总了javascript关于继承的用法,希望本文所述对大家的javascript程序设计有所帮助.分享给大家供大家参考.具体如下:代码如下: /** * 实现子类继承父类,但不会产生多余的属 ...

随机推荐

  1. position总结图

  2. html中input标签的tabindex属性

    当浏览者浏览网站时可以通过按TAB键在网页的链接中依次移动,这是一个相当方便实用的功能.但如果网页中链接太多,恐怕按TAB键就没什么作用了,这时不妨通过改变TAB键移动的顺序来突出重点,在某些重要页面 ...

  3. [转载]基于TFS实践敏捷-项目管理

    最近,一直想让团队加入敏捷开发,但TFS2010用下来,并不是令人满意,还好,TFS2012横空出世了.相比TFS2010,TFS2012改进太多了,主要体现在以下方面: Team Web Acces ...

  4. 15 BasicHashTable基本哈希表类(二)——Live555源码阅读(一)基本组件类

    这是Live555源码阅读的第一部分,包括了时间类,延时队列类,处理程序描述类,哈希表类这四个大类. 本文由乌合之众 lym瞎编,欢迎转载 http://www.cnblogs.com/oloroso ...

  5. Linux sed 批量替换多个文件中的字符串

    sed -i "s/oldstring/newstring/g" `grep oldstring -rl yourdir` 例如:替换/home下所有文件中的www.bcak.co ...

  6. saybyeto2015

    不知不觉一年又结束了,还是打算在最后一天写个总结. 今年换了工作,改变不可谓不多. 技术方面,看的书主要是 <Angularjs权威指南> <JavaScript设计模式与开发实践& ...

  7. ubuntu 开机显示错误:无法应用原保存的显示器配置

    无法应用原保存的显示器配置CRTC 63:尝试 800x600@60Hz 模式输出在 1366x768@60Hz (通过 0)CRTC 63:尝试 2560x1600@60Hz 模式输出在 1366x ...

  8. 【iOS】Quartz2D矩阵操作

    前面画基本图形时,画四边形是由几条直线拼接成的,现在有更简便的方法. 一.关于矩阵操作 1.画一个四边形 通过设置两个端点(长和宽)来完成一个四边形的绘制. 代码: - (void)drawRect: ...

  9. D3.js 坐标轴

    坐标轴,是可视化图表中经常出现的一种图形,由一些列线段和刻度组成.坐标轴在 SVG 中是没有现成的图形元素的,需要用其他的元素组合构成. D3 提供了坐标轴的组件,如此在 SVG 画布中绘制坐标轴变得 ...

  10. IntelliLock托管代码保护和许可授权管理系统软件详细介绍及下载

    IntelliLock是一个能用于控件与应用程序许可授权的100%托管的先进解决方案.与.NET Reactor提供的基于源代码保护的授权许可系统不同,IntelliLock选择了以100%托管的方式 ...