JavaScript之ES5的继承
自从有了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 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的继承的更多相关文章
- JavaScript的7种继承模式
<JavaScript模式>一书中,对于JavaScript的几种继承模式讲解得很清楚,给我提供了很大帮助.总结一下,有如下7种模式. 继承模式1--设置原型(默认模式) 实现方式: // ...
- JavaScript常用八种继承方案
更新:在常用七种继承方案的基础之上增加了ES6的类继承,所以现在变成八种啦,欢迎加高级前端进阶群一起学习(文末). --- 2018.10.30 1.原型链继承 构造函数.原型和实例之间的关系:每个构 ...
- JavaScript 常见的六种继承方式
JavaScript 常见的六种继承方式 前言 面向对象编程很重要的一个方面,就是对象的继承.A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法.这对于代码的复用是非常有用的. 大部分 ...
- JavaScript常见的六种继承方式
前言 面向对象编程很重要的一个方面,就是对象的继承.A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法.这对于代码的复用是非常有用的. 大部分面向对象的编程语言,都是通过"类 ...
- 带你理解【JavaScript】中的继承机制
前文 总所周知,继承是所有OO语言中都拥有的一个共性.在JavaScript中,它的继承机制与其他OO语言有着很大的不同,尽管ES6为我们提供了像面向对象继承一样的语法糖,但是其底层依然是构造函数,所 ...
- JavaScript对寄生组合式继承的理解
有关JavaScript的几种继承方式请移步JavaScript的几种继承方式 原型链的缺陷 SubType.prototype = new SuperType(); 这样做的话,SuperType构 ...
- web前端学习(二) javascript对象和原型继承
目录 1. JavaScrpt对象 2. 原型对象和继承 3. 对象的克隆 (1)javascript对象 在JS中,对象是属性的容器.对于单个对象来说,都由属性名和属性值构成:其中属性名需要是标识符 ...
- 【面试必备】javascript的原型和继承
原型.闭包.作用域等知识可以说是js中面试必考的东西,通过你理解的深度也就能衡量出你基本功是否扎实.今天来复习一下javascript的原型和继承,虽说是老生常谈的话题,但对于这些知识,自己亲手写一遍 ...
- Javascript的实例化与继承:请停止使用new关键字
本文同时也发表在我另一篇独立博客 <Javascript的实例化与继承:请停止使用new关键字>(管理员请注意!这两个都是我自己的原创博客!不要踢出首页!不是转载!已经误会三次了!) 标题 ...
随机推荐
- go 基础 结构体
结构体是类型中带有成员的复合类型.go语言使用结构体和结构体成员来描述真实世界的实体和实体对应的各种属性. go语言中的类型可以被实例化,使用new和&构造类型实例的类型是类型的指针. 结构体 ...
- GoJS事件
1.阻止键盘事件 myDiagram.commandHandler.doKeyDown = function () { var e = myDiagram.lastInput; // Meta(Com ...
- 面试官:你对Redis缓存了解吗?面对这11道面试题你是否有很多问号?
前言 关于Redis的知识,总结了一个脑图分享给大家 1.在项目中缓存是如何使用的?为什么要用缓存?缓存使用不当会造成什么后果? 面试官心理分析 这个问题,互联网公司必问,要是一个人连缓存都不太清楚, ...
- php最快捷的插入数据,3000万仅需5秒
<?phpheader('content-type:text/html;charset=utf-8');//采集数据$url="http://www.keepclub.com/club ...
- Azkaban3.81.x部署+坑
一.前提安装 1.1 Java1.8环境搭建 1) 下载jdk1.8并解压: # tar -zxvf jdk-8u201-linux-i586.tar.gz -C /usr/local 2) 添加Ja ...
- TCP的三次握手四次挥手理解及面试题
一.TCP概述 每一条TCP连接都有两个端点,这种端点我们叫作套接字(socket),它的定义为端口号拼接到IP地址即构成了套接字, 例如,若IP地址为192.0.0.1 而端口号为8000,那么得到 ...
- QT入门指导
罗列一些QT学习资料 1. http://www.qter.org/ 包含很多教程,包括著名的<学习之路>系列. 2. http://www.qtcn.org/bbs/index-htm- ...
- 2019-2020Nowcoder Girl初赛 题解
题目都不是很难,就是最后一题有点毒瘤 第一题:牛妹爱整除 这个你把一个进制数进行拆分,拆分成若干位,然后在取模,这样会发现如果是x进制的数,那么对x+1这个进制转化即满足条件. 举个例子:一个x进制数 ...
- 博客第一天:Typora和Markown语法初始
------------恢复内容开始------------ Markdown学习 一级标题:#+空格 二级标题:##+空格 三级标题:###+空格 四级标题:####+空格 五级标题:#####+空 ...
- C++关闭同步流 ios::sync_with_stdio(false)
说明:ios::sync_with_stdio(false) 1.这句语句是用来取消cin的同步,什么叫同步呢?就是iostream的缓冲跟stdio的同步.这就是为什么cin和cout比scanf和 ...