自从有了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. Java 网络编程 -- 基于TCP 模拟多用户登录

    Java TCP的基本操作参考前一篇:Java 网络编程 – 基于TCP实现文件上传 实现多用户操作之前先实现以下单用户操作,假设目前有一个用户: 账号:zs 密码:123 服务端: public c ...

  2. MySql --FIND_IN_SET() 函数 (转)

    例子:https://www.jianshu.com/p/b2c1ba0ba34f 举个例子来说:有个文章表里面有个type字段,他存储的是文章类型,有 1头条,2推荐,3热点,4图文 .....11 ...

  3. 小程序里json字符串转json对象需注意的地方

    一.JSON字符串转换为JSON对象 要使用上面的str1,必须使用下面的方法先转化为JSON对象: //由JSON字符串转换为JSON对象 var obj = eval('(' + str + ') ...

  4. 详解封装源码包成RPM包

    源码编译安装是最常用安装软件方式,可是面对工作量巨大时候就需要我们的RPM包上场了,统一的模块,一键安装.在面对一定数量的服务器上,RPM就可以为我们节省大量的时间. RPM可以在网上下载,但是当我们 ...

  5. 走 进 java 的 四 个 基 本 特 性

    赶上明天就还是五一c小长假了,准备在这几天写几篇原创文章,供大家一起学习. 首先今天就来好好地唠一唠,到底java的那几个特性都是什么呢?到底怎么用呢?相信一定有一些小白对此会有些懊恼,没关系的,谁还 ...

  6. Vue Cli 3 搭建单页应用项目刷新 404 问题 解决方案(以Apache为例)

    vue 项目 版本 Vue Cli 3.3 官方文档 https://router.vuejs.org/zh/guide/essentials/history-mode.html 因为本项目部署在 A ...

  7. RAID、LVM和btrfs文件系统

    一.RAID: Redundant Arrays of Inexpensive Disks,廉价磁盘冗余阵列: Redundant Arrays of Independent Disks,独立磁盘冗余 ...

  8. 数学--数论--HDU - 6395 Let us define a sequence as below 分段矩阵快速幂

    Your job is simple, for each task, you should output Fn module 109+7. Input The first line has only ...

  9. 图论--SCC缩点--Tarjan

    // Tarjan算法求有向图强连通分量并缩点 /*强连通缩点与双连通缩点大同小异,也就是说将强连通分支缩成一个点之后,没有强连通,成为有向无环图,在对图进行题目的操作.*/ #include< ...

  10. CodeForces - 262C 贪心

    Maxim always goes to the supermarket on Sundays. Today the supermarket has a special offer of discou ...