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.不可多重继承 ...
随机推荐
- tftp 服务器的配置
如果用下面一条命令能够看到服务已经启动, 则不用安装, 否则需要按 1 或 2 点安装 tftp-server 服务器. [arm@localhost arm]#netstat -a | grep t ...
- 新学MyBatis
今天学习了Mybatis入门,将知识归纳一下: 创建一个java项目之后,想使用myBatis需要完成一下几个步骤: 1.先导jar包 2.写model文件 () 3.写全局配置文件 SqlMapCo ...
- netstat -pa --unix >>test.txt
netstat -pa --unix >>test.txt 输出套接字 命名socket信息
- 10.Struts2值栈
1.什么是值栈 * 值栈就相当于Struts2框架的数据的中转站,向值栈存入一些数据.从值栈中获取到数据. * ValueStack 是 struts2 提供一个接口,实现类 OgnlValueSta ...
- c++内存相关函数
memset void *memset(void *s, int ch, size_t n); 函数解释:将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 ...
- 防HTTP慢速攻击的nginx安全配置
概述 慢速攻击,是一种ddos攻击的变体版本.通常来说,它通过向服务器发送正常的请求,只不过请求的头或者请求体的内容特别长,发送速度有特别慢,这样每一个连接占用的时间就会变得特别长,攻击者会在短时 ...
- Java环境配置:MacOS
主要是在mac os下进行java环境配置. 下载jdk http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads- ...
- 作为互联网流量入口,CDN日志大数据你该怎么玩?
CDN是非常重要的互联网基础设施,用户可以通过CDN,快速的访问网络中各种图片,视频等资源.在访问过程中,CDN会产生大量的日志数据,而随着如今越来越复杂的网络环境变化,和业务的迅速增长,日志数据变得 ...
- hdu多校第九场 1005 (hdu6684) Rikka with Game 博弈
题意: 给一个小写字母组成的字符串,每回合轮到某人时,此人可以选择让某位+1(如果是z则变回a),或者直接结束游戏. 先手希望游戏结束时字符串字典序尽量小,后手希望游戏结束时字符串字典序尽量大,求游戏 ...
- Xcode输出中文
重写NSArray和NSDictionary分类Category就OK了! 导入头文件 #import <objc/runtime.h> + (void)load { static dis ...