Javascript非构造函数的继承

一、什么是"非构造函数"的继承?

比如,现在有一个对象,叫做"中国人"。

代码如下:

var Chinese = { nation:'中国' };

还有一个对象,叫做"医生"。

代码如下:

 var Doctor ={ career:'医生' }

请问怎样才能让"医生"去继承"中国人",也就是说,我怎样才能生成一个"中国医生"的对象?

这里要注意,这两个对象都是普通对象,不是构造函数,无法使用构造函数方法实现"继承"。

二、object()方法

json格式的发明人Douglas Crockford,提出了一个object()函数,可以做到这一点。

function object(o) {

    function F() {}

    F.prototype = o;

    return new F();

  }

这个object()函数,其实只做一件事,就是把子对象的prototype属性,指向父对象,从而使得子对象与父对象连在一起。

使用的时候,第一步先在父对象的基础上,生成子对象:

代码如下:

  var Doctor = object(Chinese);

然后,再加上子对象本身的属性:

代码如下:

  Doctor.career = '医生';

这时,子对象已经继承了父对象的属性了。

代码如下:

  alert(Doctor.nation); //中国

三、浅拷贝

除了使用"prototype链"以外,还有另一种思路:把父对象的属性,全部拷贝给子对象,也能实现继承。

下面这个函数,就是在做拷贝:

  function extendCopy(p) {

    var c = {};

    for (var i in p) {
      c[i] = p[i];
    }

    c.uber = p;

 return c; }

使用的时候,这样写:

代码如下:

  var Doctor = extendCopy(Chinese);
  Doctor.career = '医生';
  alert(Doctor.nation); // 中国

但是,这样的拷贝有一个问题。那就是,如果父对象的属性等于数组或另一个对象,那么实际上,子对象获得的只是一个内存地址,而不是真正拷贝,因此存在父对象被篡改的可能。

请看,现在给Chinese添加一个"出生地"属性,它的值是一个数组。

代码如下:

  Chinese.birthPlaces = ['北京','上海','香港'];

通过extendCopy()函数,Doctor继承了Chinese。

代码如下:

  var Doctor = extendCopy(Chinese);

然后,我们为Doctor的"出生地"添加一个城市:

代码如下:

  Doctor.birthPlaces.push('厦门');

发生了什么事?Chinese的"出生地"也被改掉了!

代码如下:

  alert(Doctor.birthPlaces); //北京, 上海, 香港, 厦门
  alert(Chinese.birthPlaces); //北京, 上海, 香港, 厦门

所以,extendCopy()只是拷贝基本类型的数据,我们把这种拷贝叫做"浅拷贝"。这是早期jQuery实现继承的方式。

四、深拷贝

所谓"深拷贝",就是能够实现真正意义上的数组和对象的拷贝。它的实现并不难,只要递归调用"浅拷贝"就行了。

  function deepCopy(p, c) {

    var c = c || {};

    for (var i in p) {

      if (typeof p[i] === 'object') {

        c[i] = (p[i].constructor === Array) ? [] : {};

        deepCopy(p[i], c[i]);

      } else {

         c[i] = p[i];

      }
}

    return c; }

使用的时候这样写:

代码如下:

  var Doctor = deepCopy(Chinese);

现在,给父对象加一个属性,值为数组。然后,在子对象上修改这个属性:

代码如下:

  Chinese.birthPlaces = ['北京','上海','香港'];
  Doctor.birthPlaces.push('厦门');

这时,父对象就不会受到影响了。

代码如下:

  alert(Doctor.birthPlaces); //北京, 上海, 香港, 厦门
  alert(Chinese.birthPlaces); //北京, 上海, 香港

目前,jQuery库使用的就是这种继承方法。

以上所述就是本文的全部内容了,希望大家能够喜欢。

(0)

相关推荐

  • 深入理解javascript构造函数和原型对象

    常用的几种对象创建模式 使用new关键字创建 最基础的对象创建方式,无非就是和其他多数语言一样说的一样:没对象,你new一个呀! var gf = new Object(); gf.name = "tangwei"; gf.bar = "c++"; gf.sayWhat = function() { console.log(this.name + "said:love you forever"); } 使用字面量创建 这样似乎妥妥的了,但是宅寂的

  • JavaScript 原型继承之构造函数继承

    上回说到<JavaScript 原型继承之基础机制>,这一篇将具体说说构造函数的继承. 从一个简单的示例开始,创建描述人类的 People 构造函数: 复制代码 代码如下: function People(){ this.race = '愚蠢的人类'; } 然后,创建描述黄种人的 Yellow 构造函数: 复制代码 代码如下: function Yellow(name, skin){ this.name = name; this.skin = skin; } 要使得黄种人 Yellow 能继承

  • JavaScript构造函数详解

    构造函数就是初始化一个实例对象,对象的prototype属性是继承一个实例对象. 构造函数注意事项: 1.默认函数首字母大写 2.构造函数并没有显示返回任何东西.new 操作符会自动创建给定的类型并返回他们,当调用构造函数时,new会自动创建this对象,且类型就是构造函数类型. 3.也可以在构造函数中显示调用return.如果返回的值是一个对象,它会代替新创建的对象实例返回.如果返回的值是一个原始类型,它会被忽略,新创建的实例会被返回. function Person( name){ this

  • 浅谈js构造函数的方法与原型prototype

    把方法写在构造函数内的情况我们简称为函数内方法,把方法写在prototype属性上的情况我们简称为prototype上的方法. •函数内的方法: 使用函数内的方法我们可以访问到函数内部的私有变量,如果我们通过构造函数new出来的对象需要我们操作构造函数内部的私有变量的话, 我们这个时候就要考虑使用函数内的方法. •prototype上的方法: 当我们需要通过一个函数创建大量的对象,并且这些对象还都有许多的方法的时候;这时我们就要考虑在函数的prototype上添加这些方法. 这种情况下我们代码的

  • javascript 混合的构造函数和原型方式,动态原型方式

    我们日常JS编程中最常用的方式 有下面2种: 1.混合的构造函数和原型方式 (重点) 复制代码 代码如下: function car (sColor,iNumbers){ // 构造函数只用来定义对象的所有非函数属性,即对象的属性 this.color = sColor; this.numbers = iNumbers; this.dirvers = new Array ("Jone","Leon"); } car.prototype.showColor = fun

  • JS构造函数与原型prototype的区别介绍

    构造函数方法很好用,但是存在一个浪费内存 通过原型法分配的函数是所有对象共享的. 通过原型法分配的属性是独立.-----如果你不修改属性,他们是共享 如果我们希望所有的对象使用同一一个函数,最好使用原型法添加函数,这样比较节省内存. 例子: //----构造函数模式 为Cat对象添加一个不变的属性"type"(种类),再添加一个方法eat(吃老鼠).那么,原型对象Cat就变成了下面这样: <script> function Cat(name, color) { this.n

  • 浅谈javascript构造函数与实例化对象

    前言--讲在前面 我想有很多以前很少接触后台编程语言的初学者朋友跟我一样,对javascript里面一系列的"名词"搞的一头雾水.好像大概知道讲的是什么,但其实理解的还是不清楚:我想,学习任何一种知识,首当其冲应该把最基本的名词解释搞清楚(知道它讲的到底是什么,有助于我们更好的理解它.)即知其然知其所以然,这样对以后的进阶学习是很有帮助的.下面的简单讲一下我自己对这样一些看似不重要但又不得不清楚的知识点的理解.(若有出入,欢迎指正) 1.什么是构造函数 构造函数 ,是一种特殊的方法.主

  • Javascript非构造函数的继承

    一.什么是"非构造函数"的继承? 比如,现在有一个对象,叫做"中国人". 复制代码 代码如下: var Chinese = { nation:'中国' }; 还有一个对象,叫做"医生". 复制代码 代码如下: var Doctor ={ career:'医生' } 请问怎样才能让"医生"去继承"中国人",也就是说,我怎样才能生成一个"中国医生"的对象? 这里要注意,这两个对象都是普通对象

  • Javascript面向对象编程(三) 非构造函数的继承

    今天是最后一个部分,介绍不使用构造函数实现"继承". 一.什么是"非构造函数"的继承? 比如,现在有一个对象,叫做"中国人". 复制代码 代码如下: var Chinese = { nation:'中国' }; 还有一个对象,叫做"医生". 复制代码 代码如下: var Doctor ={ career:'医生' } 请问怎样才能让"医生"去继承"中国人",也就是说,我怎样才能生成一个&

  • Javascript面向对象编程(二) 构造函数的继承

    今天要介绍的是,如何生成一个"继承"多个对象的实例. 比如,现在有一个"动物"对象的构造函数, 复制代码 代码如下: function Animal(){ this.species = "动物"; } 还有一个"猫"对象的构造函数, 复制代码 代码如下: function Cat(name,color){ this.name = name; this.color = color; } 怎样才能使"猫"继承&

  • JavaScript的9种继承实现方式归纳

    不同于基于类的编程语言,如 C++ 和 Java,JavaScript 中的继承方式是基于原型的.同时由于 JavaScript 是一门非常灵活的语言,其实现继承的方式也非常多. 首要的基本概念是关于构造函数和原型链的,父对象的构造函数称为Parent,子对象的构造函数称为Child,对应的父对象和子对象分别为parent和child. 对象中有一个隐藏属性[[prototype]](注意不是prototype),在 Chrome 中是__proto__,而在某些环境下则不可访问,它指向的是这个

  • JavaScript程序中实现继承特性的方式总结

    概述 JavaScript的所有对象,都有自己的继承链.也就是说,每个对象都继承另一个对象,该对象称为"原型"(prototype)对象.只有null除外,它没有自己的原型对象. 原型对象的重要性在于,如果A对象是B对象的原型,那么B对象可以拿到A对象的所有属性和方法.Object.getPrototypof方法用于获取当前对象的原型对象. var p = Object.getPrototypeOf(obj); 上面代码中,对象p就是对象obj的原型对象. Object.create方

  • 深入理解JavaScript是如何实现继承的

    最近最网上看了一个人面试淘宝时的经历,然后发现了自己有好多好多不太清楚的地方,所以特此写点文章来加深自己对一些问题的理解. 文章中提到了一个问题是:JavaScript是如何实现继承的? 下面我便阐述一些在网上找到的方法和实例来解释下,借以加深自己的印象. 我们知道JavaScript中的function是万能的,除了用于的函数定义,也可以用于类的定义. JavaScript的继承,说起来也是有点怪,不像C++和一些面向对象的语言,他没有public,private等访问控制修饰,也没有impl

  • 老生常谈 关于JavaScript的类的继承

    其实最一开始学JS的时候就看过继承的实现.当时只是去试着理解从书上看来的代码段而已.今天又重新思考了一下,感觉这是一个思维探索演进的结果. 继承,即复用. 如果抛开继承的固有思想,让b复用a的成员,最简单粗暴的做法, b=a; 那么,问题来了: 对b的任何改动,就是对a的改动(同一个object嘛). 好吧,那就拷贝一份,浅拷贝不够安全的话,就用深拷贝. 问题:代码是复用了,但内存浪费了(不管是变量还是方法,在JS中都是对象). 不拷贝,只读不写,就可以用JS的原型,b.__proto__ =

  • 关于JavaScript的面向对象和继承有利新手学习

    这是一篇关于JavaScript的面向对象和继承的文章,写于1年前,作者循序渐进,对想学习JavaScript中面向对象的同学来说是很有帮助的,因此试着翻译一下,不妥之处,请指正.原文链接Objects and Inheritance in Javascript 虽然一些Javascript用户可能永远也不需要知道原型或面向对象语言的性质,但是那些来自传统面向对象的语言的开发者使用的时候会发现JavaScript的继承模型非常的奇怪.而不同的JS框架提供了各自的方法来编写类面向对象(class-

  • javascript的几种继承方法介绍

    1.原型链继承:构造函数.原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针.确认原型和实例之间的关系用instanceof. 原型链继承缺点:字面量重写原型会中断关系,使用引用类型的原型,并且子类型还无法给超类型传递参数 function Parent(){ this.name='mike'; } function Child(){ this.age=12; } //儿子继承父亲(原型链) Child.prototype

  • 深入理解javascript原型链和继承

    在上一篇文章中,介绍了原型的概念,了解到在javascript中构造函数.原型对象.实例三个好基友之间的关系:每一个构造函数都有一个"守护神"--原型对象,原型对象心里面也存着一个构造函数的"位置",两情相悦,而实例呢却又"暗恋"着原型对象,她也在心里留存了一个原型对象的位置. javascript本身不是面向对象的语言,而是基于对象的语言,对于习惯了其他OO语言的人来说,起初有些不适应,因为在这里没有"类"的概念,或者说&q

随机推荐