自从有了ES6的继承后,ES5的继承也退出了舞台,在实际开发也不会用得着,但在面试或许用的着;

先看看ES6的继承

 class Father{

             constructor(a){
console.log(a);
}
play(){
console.log("aaa");
}
static run(){
console.log("static");
}
}
class Son extends Father{
constructor(){
super();
}
}
var s=new Son();
s.play();
Father.run()
Son.run();

在ES6里只需要使用extends和super关键字即可继承父类的方法和属性(包括静态)

在ES5里没有这些关键字

ES5的继承

ES5的五种种继承方式:

  1. 对象冒充继承
  2. 原型链继承
  3. 组合继承
  4. 原型式继承
  5. 寄生式继承(重要)
  • 对象冒充继承
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指向,并执行了父类的构造函数

缺点:只能继承超类的构造函数,无法继承原型链上的方法

  • 原型链继承
 function Father(){
console.log("aa");
}
Father.prototype.b=10;
Father.prototype.play=function(){
console.log(this.b);
}
Son.prototype=new Father();
function Son(){
}
var b=new Son();
b.play();//

将父类的实例化对象赋值给子类的原型上实现的继承

缺点:覆盖子类原有的属性和方法,只能执行父类的属性和方法,无法执行父类的构造函数

  • 组合继承

  前面的两种继承(冒充,原型链)各有特点,把这两种继承组合起来称为组合继承

  function Father(_r){
this.r=_r;
console.log("aa");
}
function Son(_r){
Father.call(this,_r);//冒充,改变父类的this指向子类
}
Son.prototype=new Father(3);//原型链继承
var c=new Son(10);

使用原型链继承了父类的属性和方法,使用对象冒充继承了父类的构造函数

看起来很不错的样子,但这并不是完美的继承方式;

缺点:会覆盖子类原有的属性和方法,因为原型链继承会将父类实例化,提前执行了一次父类构造函数;当子类实例化对象后,实际上是执行了两次父类的构造函数。

使用场景:子类原本没有属性和方法,父类构造函数没有内容。

  • 原型式继承

为了解决执行两次父类构造函数使用了一个中介,在继承时就不会执行父类的构造函数

 function Father(_a){
this.a=_a
}
Father.prototype.play=function(){
console.log("aaa");
}
function Agent(){ }
Agent.prototype=Father.prototype;
function Son(){ }
Son.prototype=new Agent();
var o=new Son();
o.play();//aaa

使用了Agent的类作为中介,将父类的原型复制后,再进行实例化继承不会执行父类的构造函数;

缺点:虽然解决了构造函数执行两次的问题,但是使用该方法继承后,构造函数一次也不会执行。

  • 寄生式继承(完美继承)

封装了一个extend方法,该方法传入两个参数,分别是父类和子类

 function extend(subClass, supClass) {
function Agent() {}
Agent.prototype = supClass.prototype;
var o = subClass.prototype;
subClass.prototype = new Agent();
if (Object.assign) {
Object.assign(subClass.prototype, o);
} else {
if (Object.getOwnPropertyNames) {
var names = Object.getOwnPropertyNames(o);
for (var i = 0; i < names.length; i++) {
var desc = Object.getOwnPropertyDescriptor(names[i]);
Object.defineProperty(subClass.prototype, names[i], desc);
}
} else {
for (var prop in o) {
subClass.prototype[prop] = o[prop];
}
}
}
subClass.prototype.constructor = subClass; //防止子类的构造函数被覆盖
if (supClass.prototype.constructor === Object) {
supClass.prototype.constructor = supClass; //防止父类类的构造函数被覆盖
}
// 存储父类,方便继承构造函数调用
subClass.prototype.superClass = supClass;
}
//调用
function Father(_r) {
this.r = _r;
console.log("Father");
}
Father.prototype.play = function () {
console.log("play game");
};
function Ball(_r) {
this.superClass.call(this, _r);
}
var s = new Son(10);//Father
s.play();//play game

extend方法,使用了Object.assgin、Object.getOwnPropertyNames、Object.getOwnPropertyDescriptor、Object.defineProperty都存在兼容问题,所以进行了判断。

该方法继承集合了前四种的优点,实现了ES5的完美继承;

结语:

ES5对比ES6的继承,麻烦太多太多,以后的实际工作也不会使用;

但是在面试的时候,面试官可能会问,多学一点总没错。

JavaScript之ES5的继承的更多相关文章

  1. JavaScript的7种继承模式

    <JavaScript模式>一书中,对于JavaScript的几种继承模式讲解得很清楚,给我提供了很大帮助.总结一下,有如下7种模式. 继承模式1--设置原型(默认模式) 实现方式: // ...

  2. JavaScript常用八种继承方案

    更新:在常用七种继承方案的基础之上增加了ES6的类继承,所以现在变成八种啦,欢迎加高级前端进阶群一起学习(文末). --- 2018.10.30 1.原型链继承 构造函数.原型和实例之间的关系:每个构 ...

  3. JavaScript 常见的六种继承方式

    JavaScript 常见的六种继承方式 前言 面向对象编程很重要的一个方面,就是对象的继承.A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法.这对于代码的复用是非常有用的. 大部分 ...

  4. JavaScript常见的六种继承方式

    前言 面向对象编程很重要的一个方面,就是对象的继承.A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法.这对于代码的复用是非常有用的. 大部分面向对象的编程语言,都是通过"类 ...

  5. 带你理解【JavaScript】中的继承机制

    前文 总所周知,继承是所有OO语言中都拥有的一个共性.在JavaScript中,它的继承机制与其他OO语言有着很大的不同,尽管ES6为我们提供了像面向对象继承一样的语法糖,但是其底层依然是构造函数,所 ...

  6. JavaScript对寄生组合式继承的理解

    有关JavaScript的几种继承方式请移步JavaScript的几种继承方式 原型链的缺陷 SubType.prototype = new SuperType(); 这样做的话,SuperType构 ...

  7. web前端学习(二) javascript对象和原型继承

    目录 1. JavaScrpt对象 2. 原型对象和继承 3. 对象的克隆 (1)javascript对象 在JS中,对象是属性的容器.对于单个对象来说,都由属性名和属性值构成:其中属性名需要是标识符 ...

  8. 【面试必备】javascript的原型和继承

    原型.闭包.作用域等知识可以说是js中面试必考的东西,通过你理解的深度也就能衡量出你基本功是否扎实.今天来复习一下javascript的原型和继承,虽说是老生常谈的话题,但对于这些知识,自己亲手写一遍 ...

  9. Javascript的实例化与继承:请停止使用new关键字

    本文同时也发表在我另一篇独立博客 <Javascript的实例化与继承:请停止使用new关键字>(管理员请注意!这两个都是我自己的原创博客!不要踢出首页!不是转载!已经误会三次了!) 标题 ...

随机推荐

  1. 图解AVL树

    1:AVL树简介 二叉搜索树在一般情况下其搜索的时间复杂度为O(logn),但某些特殊情况下会退化为链表,导致树的高度变大且搜索的时间复杂度变为O(n),发挥不出树这种数据结构的优势,因此平衡二叉树便 ...

  2. 2020/4/26 大数据的zookeeper分布式安装

    大数据的zookeeper分布式安装 **** 前面的文章已经提到Hadoop的伪分布式安装.现在就在原有的基础上安装zookeeper. 首先启动Hadoop平台 [root@master ~]# ...

  3. spark2.4.5计算框架中各模块的常用实例

    本项目是使用scala语言给出了spark2.4.5计算框架中各模块的常用实例. 温馨提醒:spark的版本与scala的版本号有严格的对应关系,安装请注意. Spark Core RDD以及Pair ...

  4. Go语言: 万物皆异步

    来源:https://www.jianshu.com/p/62c0cd107da3 同步和异步.阻塞和非阻塞 首先要明确的是,同步(Synchronous)和异步(Asynchronous),阻塞(B ...

  5. Cent OS 7 添加 EPEL Nux Dextop ELRepo等源

    Cent OS 7 添加第三方yum源 CentOS由于很追求稳定性,所以官方源中自带的软件不多,因而需要一些第三方源. 比如EPEL.ATrpms.ELRepo.Nux Dextop.RepoFor ...

  6. QT 的 parent 该如何理解

    对话框是GUI程序和用户进行简短交互的顶层窗口,所谓顶层窗口即始终在主窗口之上显示.QDialog是Qt所有类型的对话框窗口的基类,它继承于QWidget,是一种容器类型组件. QWidget是所有窗 ...

  7. Linux网络服务第五章NFS共享服务

    1.笔记 NFS一般用在局域网中,网络文件系统c/s格式 服务端s:设置一个共享目录 客户端c:挂载使用这个共享目录 rpc:111远程过程调用机制 Showmount -e:查看共享目录信息 def ...

  8. Android Studio常用配置

    目录 1. 主题颜色设置 2. Logcat颜色设置 3. 类注释 4. 编译器添加背景图 4.1 第一种方式 Background Image 4.2 第二种方式 Sexy Editor 5. 修改 ...

  9. Boostrap Table学习笔记

    最近要对项目上的table进行调整,让表格能够支持更多的操作,于是接触到了boostrapTable这个插件.研究了一天,记录下学习的内容. Boostrap Table可以支持表的分页及动态显示表的 ...

  10. 用两张图告诉你,为什么你的App会卡顿?

    有什么料? 从这篇文章中你能获得这些料: 知道setContentView()之后发生了什么? 知道Android究竟是如何在屏幕上显示我们期望的画面的? 对Android的视图架构有整体把握. 学会 ...