上一篇随笔讲了封装,这一篇我们说说继承,还是那上一篇猫和狗说事儿

function Dog(name,s){
this.name=name;
this.sex=s;
}
Dog.prototype.type="犬科";
Dog.prototype.spack==function(){
alert("汪汪。。。");
}
function Cat(name,s){
this.name=name;
this.sex=s;
}
Cat.prototype.type="猫科";
Cat.prototype.spack=function(){
alert("喵喵。。。");
}

当然猫和狗都是动物,那他们就有动物的属性,比如需要吃东西,需要呼吸,喝水等等。

现在我们封装一个动物对象:

function Animal(){
this.eat="true";
this.breath="true";
    this.name="动物";
}
Animal.prototype.drink=function(){
  alert("喝水");
};

现在我们需要让猫的对象继承于动物对象的一些属性呢,我们只需要将父对象的属性绑定到子对象上就能让子对象享受父对象的属性和方法,代码如下:

function Dog(name,s){
Animal.apply(this, arguments);
this.name=name;
this.sex=s;
}
function Cat(name,s){
Animal.apply(this, arguments);
this.name=name;
this.sex=s;
}

当然这种方法也是最简单的,还有别的方法:我们可以用prototype来实现,代码如下

function Dog(name,s){
this.name=name;
this.sex=s;
}
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;
Dog.prototype.type="犬科";
Dog.prototype.spack==function(){
alert("汪汪。。。");
}

这样就让猫和狗都继承了动物的属性和方法了,让我们仔细剖析一下这种方式,在将new Animal()赋给Cat.prototype后,

function Cat(name,s){
this.name=name;
this.sex=s;
}
Cat.prototype = new Animal();
console.log(Cat.prototype);
Cat.prototype.type="猫科";
Cat.prototype.spack=function(){
alert("喵喵。。。");
}

控制台输出

Animal {
breath:"true"
eat:"true"
spack:function ()
type:"猫科"
__proto__:Object
}

打开—proto—,我们看到:

__proto__:Object
drink:function ()
constructor:function Animal()
arguments:null
caller:null
length:
name:"Animal"
prototype:Object
__proto__:function ()
[[FunctionLocation]]:test1.html:
[[Scopes]]:Scopes[]
__proto__:Objec

我们在代码里输出一下:

alert(cat1.constructor == Animal); // true

我们很明显发现constructor指向的是Animal(),在程序中它本应该指向Cat();当我们加入Cat.prototype.constructor = Cat,打开constructor再看时发现

constructor:function Cat(name,s)

有人会说我没家这句话难道不行吗,我没加上述代码程序照样继承了父对象的属性和方法,当然在这种小案例中有可能会行,但是在大项目中这样写代码会在造成继承紊乱,造成不可预知的错误,所以我么需要手动调整Cat.prototype.constructor的值,所以我们在程序中如果给prototype赋值,那么下一步必须是将对象.prototype.constructor的值重新指回到原对构造函数。

当然我们也可以让子构造函数直接继承父构造函数的prototype,代码如下:

function Cat(name,s){
this.name=name;
this.sex=s;
}
Cat.prototype = Animal.prototype;
console.log(Cat.prototype);
Cat.prototype.type="猫科";
Cat.prototype.spack=function(){
alert("喵喵。。。");
}

这种方法好处是高效,不需要重新在新建一个对象,当然缺点也很明显,此刻Animate.prototype和Cat.prototype指向同意数据源,不加Cat.prototype.constructor = Cat时Cat.prototype输出Animal(),加了之后Cat.prototype输出Cat(),貌似对了,可是Animal.prototype此刻居然也输出Cat(),原因是此刻Animate.prototype和Cat.prototype指向同意数据源,当Cat.prototype做出修改时事实上该的是它俩的数据源,所以,这种方法不可取。

当然我们还可以通过中间量的思路解决这个问题,代码如下:

function Bridge(){
}
bridge.prototype=Animal.prototype; Cat.prototype=new Bridge();
Cat.prototype.constructor = Cat;

此刻Bridgr没有添加新的方法和属性,所以它几乎不占内存,而同时我们对prototype进行修改也不会影响其父级对象的prototype

我们将上述代码封装成一个函数,以备使用:

function brideg(p,s){
var F=function(){};
F.prototype=p.prototype;
s.prototype = new F();
s.pprototype.constructor= s;
s.uber= p.prototype;
}

此处uper为子对象添加一个属性,这个属性直接指向父对象的prototype,这等于在子对象上打开一条通道,可以直接调用父对象的方法。

extend(Cat,Animal);
var cat1 = new Cat("咪咪","雄");
alert(cat1.name); // 动物

还有一种继承思路,就是将父对象的所有属性全部拷贝给子属性,那么就相当于子对象继承于父对象了

代码如下

function extend(p,s){
var p1=p.prototype;
var s1=s.prototype;
for(var i in p1){
s1[i]=p1[i];
}
s1.uper=p1;
}

调用如下:

extend2(,Animal, Cat);
var cat1 = new Cat("咪咪","雄");
alert(cat1.name); // 动物

--------------------------------------------------------我是分割线-------------------------------------------------------------

本文参考阮大神文章,地址:

http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html

js面向对象(二)——继承的更多相关文章

  1. 捋一捋js面向对象的继承问题

    说到面向对象这个破玩意,曾经一度我都处于很懵逼的状态,那么面向对象究竟是什么呢?其实说白了,所谓面向对象,就是基于类这个概念,来实现封装.继承和多态的一种编程思想罢了.今天我们就来说一下这其中继承的问 ...

  2. js面向对象之继承那点事儿根本就不是事

    继承 说道这个继承,了解object-oriented的朋友都知道,大多oo语言都有两种,一种是接口继承(只继承方法签名):一种是实现继承(继承实际的方法) 奈何js中没有签名,因而只有实现继承,而且 ...

  3. JS面向对象组件 -- 继承的其他方式(类式继承、原型继承)

    继承的其他形式: •类式继承:利用构造函数(类)继承的方式 •原型继承:借助原型来实现对象继承对象   类 : JS是没有类的概念的 , 把JS中的构造函数看做的类 要做属性和方法继承的时候,要分开继 ...

  4. JS——面向对象、继承

    创建对象的方式: 1)单体 <!DOCTYPE html> <html lang="en"> <head> <meta charset=& ...

  5. JS 面向对象之继承 -- 原型链

    ECMAScript只支持实现继承,其实现继承主要是靠原型链来实现. 原型链的基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法. 简单回顾下构造函数.原型和实例的关系: 每个构造函数都有 ...

  6. js高程(二)-----继承

    首先来讨论一下原型链,上代码 function SuperType(){ this.property = true; } SuperType.prototype.getSuperValue = fun ...

  7. js面向对象之继承-原型继承

    //animal 父类 超类 var Animal = function(name) { this.name = name; this.sayhello = function() { alert(&q ...

  8. JS 面向对象之继承---多种组合继承

    1. 组合继承:又叫伪经典继承,是指将原型链和借用构造函数技术组合在一块的一种继承方式. 下面来看一个例子: function SuperType(name) { this.name = name; ...

  9. Js面向对象构造函数继承

    构造函数继承 <!-- 创建构造函数 --> function Animal(){ this.species= '动物'; } function Dog(name,color){ this ...

  10. JS面向对象笔记二

    菜单导航,<JS面向对象笔记一>,  参考书籍:阮一峰之<JavaScript标准参考教程> 一.构造函数和new命令 二.this关键字 三.构造函数和new命令 四.构造函 ...

随机推荐

  1. java中Integer常量池

    我们先看一个关于Integer的例子 public static void main(String[] args) { // TeODO Auto-generated method stu Integ ...

  2. Linux中找不到service命令

    解决方法: 1.su -l root su root:的话只是将当前身份转为root,用户shell并没有改变.所以有些系统命令不能使用.  su -或者su -l或者su -l root,可以完全的 ...

  3. URAL 1430. Crime and Punishment(数论)

    题目链接 题意 :给你a,b,n,让你找出两个数x,y,使得n-(a*x+b*y)最小. 思路 : 分大小做,然后枚举a的倍数 #include <stdio.h> #include &l ...

  4. 说说jmap命令

    jmap命令 ps -ef| grep java root 1426 1359 0 10:30 pts/0 00:00:00 grep java root 7807 1 0 Apr28 ? 00:22 ...

  5. Mac下默认JDK路径

    2.JDK8以及JDK7安装的默认路径为:/Library/Java/JavaVirtualMachines/jdk1.8.0.jdk

  6. Materialize——扁平化卡片式网页模板

    Materialize 官网:http://www.materialscss.com/ 下载 http://pan.baidu.com/s/1kUUX2Vt CSS 颜色 背景色 <div cl ...

  7. 从Entity Framework的实现方式来看DDD中的repository仓储模式运用

    一:最普通的数据库操作 static void Main(string[] args) { using (SchoolDBEntities db = new SchoolDBEntities()) { ...

  8. Linq实战 之 DataSet操作详解

    Linq实战 之 DataSet操作详解  一:linq to Ado.Net 1. linq为什么要扩展ado.net,原因在于给既有代码增加福利.FCL中在ado.net上扩展了一些方法. 简单一 ...

  9. C#应用程序所有已经打开的窗体的集合

    获取所有打开的窗体的集合 Application.OpenForms 获取其中的某个窗体 Application.OpenForms["窗体名"]

  10. leetcode 两个数组的交集 II

    给定两个数组,写一个方法来计算它们的交集. 例如: 给定 nums1 = [1, 2, 2, 1], nums2 = [2, 2], 返回 [2, 2]. /** * @param {number[] ...