js 中继承方式小谈
题外话
前段时间面试中笔试题有这道题目:
请实现一个继承链,要求如下:
构造函数
A():构造函数中有consoleA方法,可以实现console.log("a")
实例对象 a:a 可以调用consoleA方法构造函数
B():构造函数中有consoleB方法,可以实现console.log("b")
实例对象 b:b 可以调用consoleA和consoleB方法构造函数
C():构造函数中有consoleC方法,可以实现console.log("c")
实例对象 c:c 可以调用consoleA和consoleB和consoleB方法
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 中继承方式小谈的更多相关文章
- JS中继承方式总结
说在前面:为了使代码更为简洁方便理解, 本文中的代码均将"非核心实现"部分的代码移出. 一.原型链方式关于原型链,可点击<深入浅出,JS原型链的工作原理>,本文不再重复 ...
- js各种继承方式和优缺点的介绍
js各种继承方式和优缺点的介绍 作者: default 参考网址2 写在前面 本文讲解JavaScript各种继承方式和优缺点. 注意: 跟<JavaScript深入之创建对象>一样,更像 ...
- javascript中继承方式及优缺点(三)
文以<JavaScript高级程序设计>上的内容为骨架,补充了ES6 Class的相关内容,从我认为更容易理解的角度将继承这件事叙述出来,希望大家能有所收获. 1. 继承分类 先来个整体印 ...
- 浅谈js中继承的理解和实现
一.前言 java.C#等正统面向对象语言都会提供类似extend之类的处理类的继承的方法,而javascript并没有提供专门的方法用于继承,在javascript中使用继承需要一点技巧.js中实例 ...
- js中继承的几种用法总结(apply,call,prototype)
一,js中对象继承 js中有三种继承方式 1.js原型(prototype)实现继承 <SPAN style="BACKGROUND-COLOR: #ffffff">& ...
- js中继承的方法总结(apply,call,prototype)
一,js中对象继承 js中有三种继承方式 1.js原型(prototype)实现继承 代码如下: <SPAN style="<SPAN style="FONT-SIZE ...
- js各种继承方式汇总
js中的各种继承实现汇总 首先定义一个父类: function Animal(name) { this.name = name || '动物' this.sleep = function () { c ...
- 谈谈JavaScript中继承方式
聊一聊js中的继承 一.简单继承---使用原型赋值的方式继承,将实例化的对象,赋值给子级的原型 父级构造函数 function Parent(param) { this.name = 'parent' ...
- js的继承方式分别适合哪些应用场景?
一.原型链 利用 Person.prototype = new Animal("Human") 实现继承: static式继承.能继承Animal.prototype.不可多重继承 ...
随机推荐
- elasticsearch 父子文档(十一)
说明 需求 一个产品多个区域销售 每个区域有自己的价格, 方式1冗余行,a 产品分别在 area1 area2 area3区域销售 a产品就会生成3条产品数据 搜索id去重就行了,但是问题就是 聚合 ...
- 【学术篇】规律选手再次证明自己(舒老师的胡策题 T2 LX还在迷路)
只要你不强制在线, 我就能分块. --Reflash 就算你强制在线, 我还是要分块. --Enzymii 今天做了一波舒老师的毒瘤题, T1据说很水但是没思路所以直接放掉了.. 去看了看T2好像可以 ...
- Go 位运算符
Go 位运算符 package main import "fmt" func main() { var a uint = 60 /* 60 = 0011 1100 */ var b ...
- dfs套异或的包含性——cf986C好
很好的题,想了半天,官方题解的解法更好 这种异或问题的包含性在北邮的校赛里就出现过,需要认真学习一下 /* y和所有合法的x合并,如果没有剪枝,那么复杂度爆炸总共要判(2^n*2^n) 可以考虑如下优 ...
- NX二次开发-C++的vector排序去重用法
#include <algorithm> //vector排序去重 sort( BoxNum.begin(), BoxNum.end()); BoxNum.erase(unique(Box ...
- csp-s模拟测试98
csp-s模拟测试98 $T1$??不是我吹我轻松手玩20*20.$T2$装鸭好像挺可做?$T3$性质数据挺多提示很明显? $One$ $Hour$ $Later$ 这$T1$什么傻逼题真$jb$难调 ...
- flutter 图片为空报错
imgpath != null ? Image.network(imgpath) : Container() 如果不判断imgpath 为空 network 内的url 为空就会报错
- class4_Listbox 列表部件
最终的运行效果图: #!/usr/bin/env python# -*- coding:utf-8 -*-# --------------------------------------------- ...
- java-day13
异常 指的是程序在执行过程中,出现的非正常情况,最终会导致JVM的非正常停止 异常分类:编译异常,运行期异常 异常的产生过程分析 throw关键字:指方法中抛出指定异常 使用格式:throw new ...
- 2016CCPC杭州现场赛 B-Bomb /// tarjan缩点
题目大意: 给定n个爆破点的信息 x y r w 表示爆破点位置为 (x,y) 爆破范围是以位置为圆心 半径为r的圆 引爆这个点的代价为w 引爆某个点时 其他位置在该爆破范围内的爆破点也会被引爆 求引 ...