内容简介:自从有了ES6的继承后,ES5的继承也退出了舞台,在实际开发也不会用得着,但在面试或许用的着;先看看ES6的继承在ES6里只需要使用extends和super关键字即可继承父类的方法和属性(包括静态)
自从有了ES6的继承后,ES5的继承也退出了舞台,在实际开发也不会用得着,但在面试或许用的着;
先看看ES6的继承
1 class Father{
2
3 constructor(a){
4 console.log(a);
5 }
6 play(){
7 console.log("aaa");
8 }
9 static run(){
10 console.log("static");
11 }
12 }
13 class Son extends Father{
14 constructor(){
15 super();
16 }
17 }
18 var s=new Son();
19 s.play();
20 Father.run()
21 Son.run();
在ES6里只需要使用extends和super关键字即可继承父类的方法和属性(包括静态)
在ES5里没有这些关键字
ES5的继承
ES5的五种种继承方式:
- 对象冒充继承
- 原型链继承
- 组合继承
- 原型式继承
- 寄生式继承(重要)
- 对象冒充继承
1 function Father(_r){
2 this.r=_r;
3 console.log("aa");
4 console.log(this.r);
5 }
6 Father.a=3;
7 Father.run=function(){
8 console.log(Box.a);
9 }
10 function Son(){
11 Father.call(this,3);//改变this的指向,执行父类构造函数并传参到父类
12 }
13 var b=new Son();//"aa",3
14 b.run();//TypeError
通过call或apply改变this指向,并执行了父类的构造函数
缺点:只能继承超类的构造函数,无法继承原型链上的方法
- 原型链继承
1 function Father(){
2 console.log("aa");
3 }
4 Father.prototype.b=10;
5 Father.prototype.play=function(){
6 console.log(this.b);
7 }
8 Son.prototype=new Father();
9 function Son(){
10 }
11 var b=new Son();
12 b.play();//10
将父类的实例化对象赋值给子类的原型上实现的继承
缺点:覆盖子类原有的属性和方法,只能执行父类的属性和方法,无法执行父类的构造函数
- 组合继承
前面的两种继承(冒充,原型链)各有特点,把这两种继承组合起来称为组合继承
1 function Father(_r){
2 this.r=_r;
3 console.log("aa");
4 }
5 function Son(_r){
6 Father.call(this,_r);//冒充,改变父类的this指向子类
7 }
8 Son.prototype=new Father(3);//原型链继承
9 var c=new Son(10);
10
使用原型链继承了父类的属性和方法,使用对象冒充继承了父类的构造函数
看起来很不错的样子,但这并不是完美的继承方式;
缺点:会覆盖子类原有的属性和方法,因为原型链继承会将父类实例化,提前执行了一次父类构造函数;当子类实例化对象后,实际上是执行了两次父类的构造函数。
使用场景:子类原本没有属性和方法,父类构造函数没有内容。
- 原型式继承
为了解决执行两次父类构造函数使用了一个中介,在继承时就不会执行父类的构造函数
1 function Father(_a){
2 this.a=_a
3 }
4 Father.prototype.play=function(){
5 console.log("aaa");
6 }
7 function Agent(){
8
9 }
10 Agent.prototype=Father.prototype;
11 function Son(){
12
13 }
14 Son.prototype=new Agent();
15 var o=new Son();
16 o.play();//aaa
使用了Agent的类作为中介,将父类的原型复制后,再进行实例化继承不会执行父类的构造函数;
缺点:虽然解决了构造函数执行两次的问题,但是使用该方法继承后,构造函数一次也不会执行。
- 寄生式继承(完美继承)
封装了一个extend方法,该方法传入两个参数,分别是父类和子类
1 function extend(subClass, supClass) {
2 function Agent() {}
3 Agent.prototype = supClass.prototype;
4 var o = subClass.prototype;
5 subClass.prototype = new Agent();
6 if (Object.assign) {
7 Object.assign(subClass.prototype, o);
8 } else {
9 if (Object.getOwnPropertyNames) {
10 var names = Object.getOwnPropertyNames(o);
11 for (var i = 0; i < names.length; i++) {
12 var desc = Object.getOwnPropertyDescriptor(names[i]);
13 Object.defineProperty(subClass.prototype, names[i], desc);
14 }
15 } else {
16 for (var prop in o) {
17 subClass.prototype[prop] = o[prop];
18 }
19 }
20 }
21 subClass.prototype.constructor = subClass; //防止子类的构造函数被覆盖
22 if (supClass.prototype.constructor === Object) {
23 supClass.prototype.constructor = supClass; //防止父类类的构造函数被覆盖
24 }
25 // 存储父类,方便继承构造函数调用
26 subClass.prototype.superClass = supClass;
27 }
28 //调用
29 function Father(_r) {
30 this.r = _r;
31 console.log("Father");
32 }
33 Father.prototype.play = function () {
34 console.log("play game");
35 };
36 function Ball(_r) {
37 this.superClass.call(this, _r);
38 }
39 40 var s = new Son(10);//Father
41 s.play();//play game
extend方法,使用了Object.assgin、Object.getOwnPropertyNames、Object.getOwnPropertyDescriptor、Object.defineProperty都存在兼容问题,所以进行了判断。
该方法继承集合了前四种的优点,实现了ES5的完美继承;
结语:
ES5对比ES6的继承,麻烦太多太多,以后的实际工作也不会使用;
但是在面试的时候,面试官可能会问,多学一点总没错。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 028.Python面向对象继承(单继承,多继承,super,菱形继承)
- PHP类继承、接口继承关系概述
- 面向对象:理解 Python 类的单继承与多继承
- java入门第二季--继承--java中的继承初始化顺序
- 前端基本功(七):javascript中的继承(原型、原型链、继承的实现方式)
- 组合还是继承,这是一个问题?——由模式谈面向对象的原则之多用组合、少用继承
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Flask Web开发:基于Python的Web应用开发实战
[美] Miguel Grinberg / 安道 / 人民邮电出版社 / 2014-12 / 59.00元
本书不仅适合初级Web开发人员学习阅读,更是Python程序员用来学习高级Web开发技术的优秀参考书。 • 学习Flask应用的基本结构,编写示例应用; • 使用必备的组件,包括模板、数据库、Web表单和电子邮件支持; • 使用包和模块构建可伸缩的大型应用; • 实现用户认证、角色和个人资料; • 在博客网站中重用模板、分页显示列表以及使用富文本; • 使用基于......一起来看看 《Flask Web开发:基于Python的Web应用开发实战》 这本书的介绍吧!
在线进制转换器
各进制数互转换器
HEX CMYK 转换工具
HEX CMYK 互转工具