自从有了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. gloo基本知识

    Architechture(架构) Gloo通过Envoy XDS gRPC API来动态更新Envoy配置, 更方便的控制Envoy Proxy, 并保留扩展性..本质是一个Envoy xDS配置翻 ...

  2. 数值计算方法实验之Newton 多项式插值(MATLAB代码)

    一.实验目的 在己知f(x),x∈[a,b]的表达式,但函数值不便计算或不知f(x),x∈[a,b]而又需要给出其在[a,b]上的值时,按插值原则f(xi)=yi (i=0,1,……, n)求出简单函 ...

  3. HTTPS之密钥知识与密钥工具Keytool和Keystore-Explorer

    1 简介 之前文章<Springboot整合https原来这么简单>讲解过一些基础的密码学知识和Springboot整合HTTPS.本文将更深入讲解密钥知识和密钥工具. 2 密钥知识-非对 ...

  4. 2019-2020-1 20199326《Linux内核原理与分析》第一周作业

    开篇概述 我利用假期的时间自学了实验楼上的Linux基础入门前八个实验的课程,学习过程中遇到了一些小问题.但经过查资料等方式最终还是解决了问题.现将学到的一些知识点总结下来.方便日后复习查看. 1.零 ...

  5. 13个Python图形库

    By Django中国社区 at 2013-04-27 07:49 Python的13大图形库,matplotlib功能最强大,Cairoplot最漂亮,django-chartit与Django集成 ...

  6. Scala教程之:Future和Promise

    文章目录 定义返回Future的方法 阻塞方式获取Future的值 非阻塞方式获取Future的值 Future链 flatmap VS map Future.sequence() VS Future ...

  7. Scala教程之:函数式的Scala

    文章目录 高阶函数 强制转换方法为函数 方法嵌套 多参数列表 样例类 比较 拷贝 模式匹配 密封类 单例对象 伴生对象 正则表达式模式 For表达式 Scala是一门函数式语言,接下来我们会讲一下几个 ...

  8. CYQ.Data 轻量数据层之路 使用篇-MProc 存储过程与SQL 视频[最后一集] H (二十八)

    2019独角兽企业重金招聘Python工程师标准>>> 说明: 本次录制主要为使用篇:CYQ.Data 轻量数据层之路 使用篇五曲 MProc 存储过程与SQL(十六)   的附加视 ...

  9. Alpine Linux 3.9.2 发布,轻量级 Linux 发行版

    开发四年只会写业务代码,分布式高并发都不会还做程序员?   Alpine Linux 3.9.2 已发布,Alpine Linux 是一款面向安全的轻量级 Linux 发行版,体积十分的小. Alpi ...

  10. 交换机上的MAC地址表

    拓扑图: 1.首先在R1上的配置: R1(config)#int R1(config)#interface g R1(config)#interface gigabitEthernet 0/0 R1( ...