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

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. ubuntu 16.04启用root和ssh登录

    1.设置用户密码 sudo passwd root 2.vim /usr/share/lightdm/lightdm.conf.d/50-ubuntu.conf 末尾添加:greeter-show-m ...

  2. #2002 无法登录 MySQL 服务器

    phpMyAdmin无法登录,输入用户名和密码后点击“执行”后一直报 “#2002 无法登录 MySQL 服务器”. 解决办法,将 “phpMyAdmin/libraries”文件夹下的config. ...

  3. 常见的MIME

    "css": "text/css", "gif": "image/gif", "html": &qu ...

  4. VMware安装Ubuntu分辨率无法适应屏幕的解决方法

    ​ 一开始虚拟机安装Ubuntu的时候遇到分辨率无法适应屏幕的时候,百度了一大堆都说使用xrandr命令来修改分辨率,但是还是无法适应1920x1080的屏幕,强迫症表示非常难受! ​ 然后在不知道是 ...

  5. oracle通过job执行procedure

    1. 先创建一个FUNCTION CREATE OR REPLACE FUNCTION GET_TIMEOUT_PROGRAM(i_customerNo IN TK_CUST_PROG_D.CUSTO ...

  6. C#winform自定义滚动条

    1.控件 一个UserControl作为ScrollBg,一个panel作为ScrollBar 2.实现功能 (1)设置滚动条背景颜色和背景图片 (2)设置滚动条滑块的背景颜色和背景图片 (3)鼠标左 ...

  7. 13种PDF转图片的案列

    Acrobat.dllc#PDFPDFRender4NET.dllpdf转图片 GitHub Clone Adress : https://github.com/stone0090/OfficeToo ...

  8. 菜鸟的Xamarin.Forms前行之路——从新建项目到APP上架各种报错问题解决方法合集(不定时更新)

    出自:博客园-半路独行 原文地址:http://www.cnblogs.com/banluduxing/p/7425791.html 本文出自于http://www.cnblogs.com/banlu ...

  9. 聊聊 JDK 阻塞队列源码(ReentrantLock实现)

    项目中用到了一个叫做 Disruptor 的队列,今天楼主并不是要介绍 Disruptor 而是想巩固一下基础扒一下 JDK 中的阻塞队列,听到队列相信大家对其并不陌生,在我们现实生活中队列随处可见, ...

  10. c# 用户输入一个字符串,求字符串的长度

    C#  用户输入一个字符串,求字符串的长度使用字符串的length: class Program { static void Main(string[] args) { Console.WriteLi ...