题外话

前段时间面试中笔试题有这道题目:

请实现一个继承链,要求如下:

  • 构造函数A():构造函数中有consoleA方法,可以实现console.log("a")

    实例对象 a:a 可以调用consoleA方法

  • 构造函数B():构造函数中有consoleB方法,可以实现console.log("b")

    实例对象 b:b 可以调用consoleAconsoleB方法

  • 构造函数C():构造函数中有consoleC方法,可以实现console.log("c")

    实例对象 c:c 可以调用consoleAconsoleBconsoleB方法

ok,这个题目暂时搁置,再回到这个问题之前,我们先来看看 js 的继承方式

约定

// 父类
function Super() {
this.name = "parent0";
this.colors = ["red", "blue", "yellow"];
}
Super.prototype.sex = "男";
Super.prototype.say = function() {
console.log(" Oh,My God! ");
};

构造继承

原理

通过使用 call、apply 方法可以在新创建的对象上执行构造函数,用父类的构造函数来增加子类的实例

实现

function Sub() {
Super.call(this);
this.type = "sub";
} var s = new Sub(); console.log(s.colors); //[ 'red', 'blue', 'yellow' ]
s.say(); //报错 sub.say is not a function

优缺点

  • 优点:简单明了,直接继承超类构造函数的属性和方法
  • 缺点:无法继承原型链上的属性和方法

原型链式继承(借用原型链实现继承)

实现

function Sub() {
this.type = "sub";
}
Sub.prototype = new Super();
var s1 = new Sub();
var s2 = new Sub();
sub1.colors.push("black");
console.log(s1.colors); //[ 'red', 'blue', 'yellow', 'black' ]
console.log(s2.colors); //[ 'red', 'blue', 'yellow', 'black' ]
sub1.say();

我们实例化了两个 Sub,在实例 s1 中为父类的 colors 属性 push 了一个颜色,但是 s2 也被跟着改变了。造成这种现象的原因就是原型链上中的原型对象它俩是共用的。这不是我们想要的,s1 和 s2 这个两个对象应该是隔离的,

组合继承

这里所谓的组合是指组合借用构造函数和原型链继承两种方式。

function Sub() {
Super.call(this);
this.type = "sub";
}
Sub.prototype = new Super();
var s1 = new Sub();
var s2 = new Sub();
s1.colors.push("black");
console.log(s1.colors); //[ 'red', 'blue', 'yellow', 'black' ]
console.log(s2.colors); //[ 'red', 'blue', 'yellow' ]

可以看到,s2和s1两个实例对象已经被隔离了,但这种方式仍有缺点。父类的构造函数被执行了两次,第一次是Sub.prototype = new Super(),第二次是在实例化的时候,这是没有必要的。那我们就继续优化吧!!

组合式继承优化1

function Sub(){
Super.call(this)
this.type = "sub";
}
Sub.prototype=Super.prototype
var s1=new Sub()
var s2=new Sub()

但是请看以下代码

console.log(s1.constructor.name);//Super

我们还可以用.constructor来观察对象是不是某个类的实例:从这里可以看到,s1的构造函数居然是父类Super,而不是子类sub,这显然不是我们想要的。

组合式继承优化2

function Sub(){
Super.call(this)
this.type = "sub";
}
Sub.prototype=Super.prototype
Sub.constructor=Sub
var s1=new Sub()
var s2=new Sub()
console.log(s1 instanceof Sub);//true
console.log(s1 instanceof Super);//true
console.log(s1.constructor.name);//Super

perfect!!

开题解答

回到开头的问题中来,

function A(){}
A.prototype.consoleA=function(){
console.log("a")
}
function B(){
A.call(this)
}
B.prototype.consoleB=function(){
console.log("b")
}
Object.assign(B.prototype,A.prototype)
function C(){
B.call(this)
}
C.prototype.consoleC=function(){
console.log("c")
}
Object.assign(C.prototype,B.prototype)

参考资料

前端面试必备之JS继承方式总结

大前端之路----JS继承的六种方式

js 中继承方式小谈的更多相关文章

  1. JS中继承方式总结

    说在前面:为了使代码更为简洁方便理解, 本文中的代码均将"非核心实现"部分的代码移出. 一.原型链方式关于原型链,可点击<深入浅出,JS原型链的工作原理>,本文不再重复 ...

  2. js各种继承方式和优缺点的介绍

    js各种继承方式和优缺点的介绍 作者: default 参考网址2 写在前面 本文讲解JavaScript各种继承方式和优缺点. 注意: 跟<JavaScript深入之创建对象>一样,更像 ...

  3. javascript中继承方式及优缺点(三)

    文以<JavaScript高级程序设计>上的内容为骨架,补充了ES6 Class的相关内容,从我认为更容易理解的角度将继承这件事叙述出来,希望大家能有所收获. 1. 继承分类 先来个整体印 ...

  4. 浅谈js中继承的理解和实现

    一.前言 java.C#等正统面向对象语言都会提供类似extend之类的处理类的继承的方法,而javascript并没有提供专门的方法用于继承,在javascript中使用继承需要一点技巧.js中实例 ...

  5. js中继承的几种用法总结(apply,call,prototype)

    一,js中对象继承 js中有三种继承方式 1.js原型(prototype)实现继承 <SPAN style="BACKGROUND-COLOR: #ffffff">& ...

  6. js中继承的方法总结(apply,call,prototype)

    一,js中对象继承 js中有三种继承方式 1.js原型(prototype)实现继承 代码如下: <SPAN style="<SPAN style="FONT-SIZE ...

  7. js各种继承方式汇总

    js中的各种继承实现汇总 首先定义一个父类: function Animal(name) { this.name = name || '动物' this.sleep = function () { c ...

  8. 谈谈JavaScript中继承方式

    聊一聊js中的继承 一.简单继承---使用原型赋值的方式继承,将实例化的对象,赋值给子级的原型 父级构造函数 function Parent(param) { this.name = 'parent' ...

  9. js的继承方式分别适合哪些应用场景?

    一.原型链 利用 Person.prototype = new Animal("Human") 实现继承: static式继承.能继承Animal.prototype.不可多重继承 ...

随机推荐

  1. 2019-7-15-WPF-测试触摸设备发送触摸按下和抬起不成对

    title author date CreateTime categories WPF 测试触摸设备发送触摸按下和抬起不成对 lindexi 2019-7-15 9:3:51 +0800 2019-0 ...

  2. Bash 脚本 set 命令教程

    http://www.ruanyifeng.com/blog/2017/11/bash-set.html set命令是 Bash 脚本的重要环节,却常常被忽视,导致脚本的安全性和可维护性出问题.本文介 ...

  3. redis设置自动启动

    按照如下操作即可(可以自定义目录) mkdir /redis cd /redis wget http://download.redis.io/releases/redis-4.0.1.tar.gz t ...

  4. mysql-5.5.17-win64 安装方法

    双击mysql-5.5.17-win64.msi,即开始安装,出现如下界面 2 点击next,出现如下界面,默认为Typical,改选为Custom,单击Next 3 选择MySQL Server后, ...

  5. bzoj1009题解

    [解题思路] 先KMP出fail数组,再用fail数组求出M[i][j],表示上一次匹配到第i位,这次可以遇到多少种不同的字符,使之转而匹配到第j位. 设集合S=[1,m]∩N 又设f[i][j]表示 ...

  6. Android获取Root权限之后的静默安装实现代码示例分析

    转:http://blog.csdn.net/jiankeufo/article/details/43795015 Adroid开发中,我们有时会遇到一些特殊功能的实现,有些功能并没有太高技术难度,但 ...

  7. Jboss集群(五)--F5硬件负载均衡器双击热备 + Jboss集群终极实现

    BIG/IP利用定义在其上面的虚拟IP地址来为用户的一个或多个应用服务器提供服务.因此,它能够为大量的基于TCP/IP的网络应用提供服务器负载均衡服务.BIG/IP连续地对目标服务器进行L4到L7合理 ...

  8. 牛客多校第十场 E Hilbert Sort 递归,排序

    题意: 给你一个方阵,再在方阵上给定一些点,按照希尔伯特曲线经过的先后顺序为这些点排序 题解: 定义好比较函数后直接调用排序算法即可. 希尔伯特曲线本来就是用于二维到一维的映射的,因此我们可以考虑对于 ...

  9. Python 爬虫-抓取中小企业股份转让系统公司公告的链接并下载

    系统运行系统:MAC 用到的python库:selenium.phantomjs等 由于中小企业股份转让系统网页使用了javasvript,无法用传统的requests.BeautifulSoup库获 ...

  10. pure-ftpd 配置

    # Disallow anonymous connections. Only allow authenticated users. NoAnonymous yes # If you want simp ...