博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
面向对象编程里面的继承
阅读量:4655 次
发布时间:2019-06-09

本文共 3117 字,大约阅读时间需要 10 分钟。

上一节我简单写了创建对象的集中方法,关于对象,还有一个有趣的概念,那就是继承。

OO语言,Object-Oriented,即面向对象编程。JS实现继承的方式叫做——实现继承,实现继承又是通过原型链来实现的。

  (#`皿´)   吼吼,听听这绕口令,就问你怕不怕!    (#`皿´)   

 

一、原型链

构造函数,原型和实例的关系,先默写吧。

 每个构造函数,都有一个原型对象。原型对象里包含一个指向构造函数的指针。而实例里包含一个指向原型函数的指针。他们之间的关系可以描述为:实例-->原型对象-->构造函数。

现在,我们假设,某一个原型对象a其实是某个实例类型A。那么,原型对象a(实例A)-->原型对象a的构造函数B,同时也是实例A-->A的原型对象(构造函数B)-->A的构造函数C。这样,一条原型链就出来了。

function SuperType(){    this.property=true;}SuperType.prototype.getSuperValue=function(){    return this.property;}function Sub(){    this.sub='subValue';}Sub.prototype=new SuperType();//通过初始化继承了SuperTypeSub.prototype.getSub=function(){    return this.sub;}var instance=new Sub();console.log(instance.getSub());//subValueconsole.log(instance.getSuperValue());//true

 上面代码可以看到,通过继承,sub拥有了superType的属性和方法。而他的实现方法就是:创建一个SuperType的实例,然后将这个实例赋给sub的prototype属性中! 

还有一个默认的链条。由于所有的默认原型都是Object的实例,因此默认原型都会包含一个内部指针,指向Object.prototype.这也就是为什么所有的自定义类型都会继承toString()、valueOf()等默认方法的原因。

  

二、确定原型和实例的关系

第一种方法:采用instanceof操作符。只要用这个操作符测试实例与原型链中出现过的构造函数,结果就会返回true。

console.log(instance instanceof Object);//trueconsole.log(instance instanceof Sub);//trueconsole.log(instance instanceof SuperType);//true

 

第二种方法:isPrototypeOf()方法。注意,顺序反过来。这个方法是属于对象的prototype属性的。

console.log(Object.prototype.isPrototypeOf(instance));//trueconsole.log(Sub.prototype.isPrototypeOf(instance));//trueconsole.log(SuperType.prototype.isPrototypeOf(instance));//true

 

 

三、原型链存在的问题

function Super(){    this.colors=['red','blue','pink'];}function Sub(){}Sub.prototype=new Super();var obj1=new Sub();obj1.colors.push('black');console.log(obj1.colors);//["red", "blue", "pink", "black"]var obj2=new Sub();console.log(obj2.colors);//["red", "blue", "pink", "black"]

 

看见没有,obj1把obj2给玷污了!

包含应用类型值的原型属性会被所有实例共享!所以,这就是我们为什么要在构造函数中定义属性,而不是在原型对象中定义属性。

在通过原型实现继承时,原型实际上会变成另一个类型的实例,于是,原先的是咧也就变成了现在的原型属性了。

 

四、借用构造函数继承=伪造对象继承=经典继承

为了弥补原型链继承的缺陷,就有了经典继承。基本思想是:在子类型构造函数的内部调用超类型构造函数。

函数是在特定环境中执行代码的对象,通过使用apply()和call()方法,可以在新创建的对象上执行构造函数。 

function Super(){    this.colors=['red','blue','pink'];}function Sub(){    //用call()方法继承Super    Super.call(this);}var obj1=new Sub();obj1.colors.push('black');console.log(obj1.colors);//["red", "blue", "pink", "black"]var obj2=new Sub();console.log(obj2.colors);//['red','blue','pink']

 call()方法,“借调”了超类型构造函数。

相对原型链来说,构造函数的优点是:可以在子类型构造函数中向超类型的构造函数传递参数。比如下面代码:

function Super(name){    this.name=name;}function Sub(){    Super.call(this,'Alice');    this.age=18;}var instance=new Sub();console.log(instance.name+instance.age);//Alice18

 

 

五、组合继承=伪经典继承=原型链+构造函数

组合继承,又叫伪经典继承,将原型链与构造函数组合到一起,实现的继承模式。

function Super(name){    this.name=name;    this.color=['red','blue'];}Super.prototype.sayName=function(){    console.log(this.name);}function Sub(name,age){    Super.call(this,name);    this.age=age;    }Sub.prototype=new Super();Sub.prototype.constructor=Sub;Sub.prototype.sayAge=function(){    console.log(this.age);}var obj1=new Sub("Alice",18);obj1.color.push('black');console.log(obj1.color);//Array(3) ["red", "blue", "black"]obj1.sayAge();//18obj1.sayName();//Alice

 

组合模式避免了两者的缺点,是js中最常用的继承模式。instanceofhe isPrototypeOf()能够识别基于组合继承创建的对象。

 

转载于:https://www.cnblogs.com/qingshanyici/p/10497766.html

你可能感兴趣的文章
HashMap
查看>>
Android广播机制概述
查看>>
[javascript]9宫格拖拽拼图游戏 puzzle
查看>>
Entity Framework底层操作封装(3)
查看>>
InputStream 转换 InputStreamReader再转换BufferedReader
查看>>
在线程池中的使用spring aop事务增强
查看>>
继续深入了解Cookie 和 Session
查看>>
再看《操作系统》--处理机管理
查看>>
亚马逊的负载均衡(Amazon Load Balancing)
查看>>
Java学习之Comparable与Comparator的区别
查看>>
ASP:Checkbox验证非空的一种方法
查看>>
[CQOI2013]新Nim游戏 线性基
查看>>
我的成就故事
查看>>
VB6.0 API 累计
查看>>
第十周学习进度博客
查看>>
Ecshop 最小起订量如何设置
查看>>
不使用其他变量实现两变量互换
查看>>
bcp功能
查看>>
xcode项目打不开:incompatible project version问题
查看>>
学习网站
查看>>