红宝书 第6章整理——继承部分
来源:互联网 发布:活动网络正在识别 编辑:程序博客网 时间:2024/06/01 07:48
继承
第一部分讲的都是如何创建一个类型,如果要创建多个类型,而且类型中属性方法相似度非常大,那么久可以直接用继承的方法来创建其它类 。
① 原型链
1、原型链定义+实现
继承:是面向对象语言中一个非常棒的概念。一般的面向对象语言中都支持两种继承:接口继承+实现继承。
但是!!由于js中函数没有签名,所以只支持实现继承。
其实现继承主要依靠原型链来实现的。
下面是一个继承的例子:
////先用组合式构造一个类:Superfunction Super(){ this.value = true;}Super.prototype.getvalue = function(){ return this.value;};////再用构造函数创建第二个新类型:Subfunction Sub(){ this.subvalue = false;}//注意,接下来的方法直接用new Super构造Sub.prototype = new Super();Sub.prototype.getsubvalue = function(){ //再创建一个新方法 return this.subvalue;};///实例化var instanse = new Sub();instanse.getsubvalue(); // "true"
注意Sub.prototype = new Super(); 正常此处应该写Sub.prototype的方法,但是此处直接将Sub.prototype指向了Super对象。
这时就形成了一个原型链。
instanse(实例)----->Sub(类型)----->Sub.prototype(原型)----->Super(原型)----->Super.prototype(原型)
在这个链中,后面的都算是Sub的原型,其中的东西都是可共享的。
Sub相当于可以使用除了自己后加入的方法getsubvalue,和自己的属性subvalue以外,还可以使用Super中的value和getvalue方法。
当实例中调用一个方法时,会一级一级向上找。
2、默认的原型链
实际上instanse完整的原型链为:
instanse(实例)----->Sub----->Sub.prototype----->Super----->Super.prototype----->Object----->Object.prototype
别忘了所有的函数都有一个终极的默认原型Object的实例,Object当然自己也有一个Object.prototype。
这就是为什么所有对象都有toString(),valueOf()的方法,不管有没有意义,都可以调用,因为这些都是终极原型Object.prototype中的方法.......必须得继承
3、确定原型与实例的方法
两种方法:
instanceof:
A 是实例of 类型
friend instanceof Person; //true
friend instanceof Object; //true
isPrototypeOf:
原型 . 是原型of ( 实例)
Person.prototype.isPrototypeOf(friend); //true
Person.prototype.isPrototypeOf(Object); //true
4、子级添加方法
子类添加新方法,OK 。直接用子类的prototype中写就可以
当子类中创建了一个与父级中同名的方法(即重写超类型的方法),OK。
此时就会屏蔽掉超类型中原方法,注意不会对超类型产生影响,仅在子类的实例化中会执行新方法。
5、缺点
两点:
1、引用类型共享问题
instanse(实例)----->Sub(类型)----->Sub.prototype(原型)----->Super(原型)----->Super.prototype(原型)
就这个原型链中,我们可以看出Super的构造函数也变成了原型之一,这就导致了如果Super构造函数中有属性值为引用类型(比如数组型),就会被共享,当实例中将其改变后,所有的都会被改。
之前上一部分讲创建一个类型时,出现过这种问题的是纯纯的原型模式。为了避免这个问题我们才引入的构造原型组合式。
但是此处因为继承,构造函数的也变成了原型模式。
2、不能向上级传参
只能从父级向下引用
解决办法——组合继承
② 组合继承
1、实现
组合继承的思路:因为之前构造函数被继承的缘故,导致被共享,那么在新的类型中,我们不把构造函数直接继承过来,而是变成调用父级的方式。我们可以运用call,或者apply来现场调用。
///首先还是创建父级Superfunction Super(name){ this.name = name; this.color = ["red" , "blue"];}Super.prototype.say = function(){ alert(this.name);};///接下来创建新的类Subfunction Sub(name,age){ Super.call(this , name); //要继承的name与color,用call函数在此处调用Super的构造函数 this.age = age; // 自己新创建的属性age}Sub.prototype = new Super(); //方法直接继承Sub.prototype.sayage = function(){ // 自己的新方法 alert(this.age);};//测试一下var a = new Sub("jack",20); // 创建Sub实例a.color.push("green"); //将引用类型做更改alert(a.color); //red,blue,greena.say(); //jacka.sayage(); //20var b = new Sub("tom",33); // 创建Sub实例alert(b.color); //red,blueb.say(); //tomb.sayage(); //33
2、缺点
无论什么情况下,都会调用两次超类型的构造函数(就是父级的构造函数)
Super.call(this , name); //要继承的name与color,用call函数在此处调用Super的构造函数
Sub.prototype = new Super(); //方法直接继承
顺序是先new Super(); 这时实际上已经有了一套name,color,位置在超类型中,被继承
只不过后来的call又实现了一套子类中自己的name,color,将超类型中的屏蔽了。
解决办法——寄生组合式
③原形式继承+寄生式继承+寄生组合式继承
原型式:可以在没有预先定义构造函数的情况下实现继承,本质是先浅复制,再改造
寄生式:与原形式类似,也是先创建一个对象,然后再改造
寄生组合式:集寄生式和组合式,是实现引用类型最理想的继承方式。,只调用一次超类型的构造函数
- 红宝书 第6章整理——继承部分
- 红宝书 第6章整理——创建对象
- 红宝书 第3章 整理——数据类型+函数入门
- 红宝书 第4章整理——变量+内存管理
- 红宝书 第7章整理——函数+闭包
- 红宝书 第8章整理——BOM
- 红宝书 第9章整理——客户端检测
- 红宝书 第10章整理——DOM
- 红宝书 第11章整理——DOM扩展
- 红宝书 第13章整理——事件
- 红宝书 第14章整理——表单
- 红宝书 第15章整理——canvas
- 红宝书 第17章整理——错误处理
- 红宝书 第18章整理——XML入门
- 红宝书 第18章整理——XML与JS
- 红宝书 第18章整理——XPath
- 红宝书 第10章整理——E4X
- 红宝书 第20章整理——JSON
- 企业级软件质量管控
- HDU 2084:数塔(动态规划)
- Window网络编程之TCP通信
- Codeforces 789 C Functions again (dp)
- C语言下的创建一个数组, 实现函数init()初始化数组、 实现empty()清空数组、 实现reverse()函数完成数组元素的逆置。 要求:自己设计函数的参数,返回值。
- 红宝书 第6章整理——继承部分
- Ubuntu 16.04 下keras安装和mnist测试
- Spring Security学习(二)Spring Security Guides
- 使用matplotlib.pyplot + xlrd + pandas使租房价格面积数据关系可视化
- python的输出
- HDU 1102Constructing Roads(最小生成树)
- POJ2155
- LeetCode #13 Roman to Integer
- Android studio-gradle