javaScript继承的几种实现方式?
js继承总共分成5种,包括构造函数式继承、原型链式继承、组合式继承、寄生式继承和寄生组合式继承。
构造函数式继承
首先来看第一种,构造函数式继承,顾名思义,也就是利用函数去实现继承;构造函数继承,使用call和apply两个方法可以实现改变方法中的this
// 父类构造函数
function Parent(color) {
this.color = color;
this.print = function() {
console.log(this.color);
}
}
现在要编写一个子类函数来继承这个父类,如下:
// 子类构造函数
function Son(color) {
Parent.call(this, color);
- 优点:所有的基本属性独立,不会被其他实例所影响;
- 缺点:所有希望共享的方法和属性也独立了,没有办法通过修改父类某一处来达到所有子实例同时更新的效果;同时,每次创建子类都会调用父类构造函数一次,所以每个子实例都拷贝了一份父类函数的内容,如果父类很大的话会影响性能;
原型链继承
function Parent() {
this.color = 'red';
this.print = function() {
console.log(this.color);
}
}
function Son() {
}
我们有一个父类和一个空的子类;
Son.prototype = new Parent();
Son.prototype.constructor = Son;
接着我们把子函数的原型属性赋值给了父函数的实例;
var son1 = new Son();
son1.print(); // red
最后新建子类实例,调用父类的方法,成功拿到父类的color和print属性方法;
我们重点来分析一下下面两行代码:
Son.prototype = new Parent();
Son.prototype.constructor = Son;
这段代码中,子函数的原型赋给了父函数的实例,我们知道prototype是函数中的一个属性,js的一个特性就是:如果一个对象某个属性找不到,会沿着它的原型往上去寻找,直到原型链的最后才会停止寻找。
回到代码,我们看到最后实例son成功调用了Print方法,输出了color属性,这是因为son从函数Son的prototype属性上面去找到的,也就是从new Parent这个对象里面找到的;
这种方式也不是真正的继承,因为所有的子实例的属性和方法,都在父类同一个实例上了,所以一旦某一个子实例修改了其中的方法,其他所有的子实例都会被影响,来看下代码:
function Flower() {
this.colors = ['黄色', '红色'];
this.print = function () {
console.log(this.colors)
}
}
function Rose() {}
Rose.prototype = new Flower();
Rose.prototype.constructor = Rose;
var r1 = new Rose();
var r2 = new Rose();
console.log(r1.print()); // [ '黄色', '红色' ]
console.log(r1.print()); // [ '黄色', '红色' ]
r1.colors.push('紫色');
console.log(r1.print()); // [ '黄色', '红色', '紫色' ]
console.log(r2.print()); // [ '黄色', '红色', '紫色' ]
还是刚才的例子,这次Rose子类选择了原型链继承,所以,子实例r1修改了colors之后,r2实例的colors也被改动了,这就是原型链继承不好的地方。
来总结下原型链继承的优缺点:
- 优点:很好的实现了方法的共享;
- 缺点:正是因为什么都共享了,所以导致一切的属性都是共享的,只要某一个实例进行修改,那么所有的属性都会变化;
组合式继承
function Parent(color) {
this.color = color;
}
Parent.prototype.print = function() {
console.log(this.color);
}
function Son(color) {
Parent.call(this, color);
}
Son.prototype = new Parent();
Son.prototype.constructor = Son;
var son1 = new Son('red');
son1.print(); // red
var son2 = new Son('blue');
son2.print(); // blue
上面代码中,在Son子类中,使用了Parent.call来调用父类构造函数,同时又将Son.prototype赋给了父类实例;为什么要这样做呢?为什么这样就能解决上面两种继承的问题呢?
我们接着分析一下,使用Parent.call调用了父类构造函数之后,那么,以后所有通过new Son创建出来的实例,就单独拷贝了一份父类构造函数里面定义的属性和方法,这是前面构造函数继承所提到的一样的原理;
然后,再把子类原型prototype赋值给父类的实例,这样,所有子类的实例对象就可以共享父类原型上定义的所有属性和方法。这也不难理解,因为子实例会沿着原型链去找到父类函数的原型。
因此,只要我们定义父类函数的时候,将私有属性和方法放在构造函数里面,将共享属性和方法放在原型上,就能让子类使用了。
以上就是组合式继承,它很好的融合了构造函数继承和原型链继承,发挥两者的优势之处,因此,它算是真正意义上的继承方式。
javaScript继承的几种实现方式?的更多相关文章
- js(javascript) 继承的5种实现方式
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt240 js继承有5种实现方式:1.继承第一种方式:对象冒充 functio ...
- javascript继承有5种实现方式
1.对象冒充 function Parent(username){ this.username = username; this.hello = function(){ alert(this.user ...
- JS学习笔记——JavaScript继承的6种方法(原型链、借用构造函数、组合、原型式、寄生式、寄生组合式)
JavaScript继承的6种方法 1,原型链继承 2,借用构造函数继承 3,组合继承(原型+借用构造) 4,原型式继承 5,寄生式继承 6,寄生组合式继承 1.原型链继承. <script t ...
- 面向面试编程——javascript对象的几种创建方式
javascript对象的几种创建方式 总共有以下几个模式: 1.工厂模式 2.构造函数模式 3.原型模式 4.混合构造函数和原型模式 5.动态原型模式 6.寄生构造函数模式 7.稳妥构造函数模式 1 ...
- JavaScript脚本的两种放置方式
JavaScript脚本的两种放置方式 1在body里用 script标签引用 2 直接写在<script></script>标签之中
- JavaScript继承的几种实现
0 什么是继承 继承就是获得存在对象已有的属性和方法的一种方式. [2019.4.26 更新]今日又重新学习了一下JS的继承,在这里整理一下以前的笔记并补充一些新的感悟. 1 JS中继承的几种实现方法 ...
- javascript继承的三种模式
javascript继承一般有三种模式:组合继承,原型式继承和寄生式继承: 1组合继承:javascript最为广泛的继承方式通过原型链实现对原型属性和方法的继承,通过构造函数实现对实例属性的继承,同 ...
- JavaScript 函数的两种声明方式
1.函数声明的方式 JavaScript声明函数有两种选择:函数声明法,表达式定义法. 函数声明法 function sum (num1 ,num2){ return num1+num2 } 表达式定 ...
- javascript中对象两种创建方式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
随机推荐
- 为什么换了电脑安装MindManager提示密钥失效?
相信很多MindManager用户遇到过这样的问题,不想在原电脑上使用MindManager思维导图软件,想要换电脑安装,但是提示该许可证密钥失效了.下面文章就教大家如何解决这个问题: 我们在Mind ...
- 【基于Puppeteer前端自动化框架】【二】PO模式,断言(如何更简便逻辑的写测试代码)
一.概要 前面介绍了Puppeteer+jest+TypeScript做UI自动化,但是这知识基础的,我们实现自动化要考虑的很多,比如PO模式,比如配置文件,比如断言等等.下面就来一一实现我是怎么用p ...
- 工作中使用mongodb
写了一个mongodb的基类 1 <?php 2 3 namespace BI\Service\MongoDB; 4 5 use MongoDB\Driver\BulkWrite; 6 use ...
- Yali 19 - 8 - 6 test T2 猪国(pig) 题解
T2 猪国 题⽬描述 猪国是⼀个由 \(n\) 个城市组成的国家. 国王意识到了"要致富,先修路"这句话的重要性,它决定⼤规模修路.不巧的是,猪国的 猪们不太会⼯程,于是只能请隔壁 ...
- 浅谈 倍增/ST表
命题描述 给定一个长度为 \(n\) 的序列,\(m\) 次询问区间最大值 分析 上面的问题肯定可以暴力对吧. 但暴力肯定不是最优对吧,所以我们直接就不考虑了... 于是引入:倍增 首先,倍增是个什么 ...
- H3CNE认证(题库)
H3CNE考试的题库,均为发烧友收集的,拥有将近认证考试的百分之八十五的题,但答案不具备官方性,但是题库具有解析. https://huxiaoyao.lanzous.com/b01tr2skd 密码 ...
- Java继承的两道实验题目
设计一个表示二维平面上点的类Point,包含有表示坐标位置的Protect类型的成员变量 获取和设置x和y值的public方法 package classwork_6; public class Po ...
- java线程与内存的关系
转载: https://blog.csdn.net/hellozhxy/article/details/91972846
- .NetCore项目Linux部署总结
Linux部署文档 1.常用指令 find [/根目录 .当前目录] -name [文件名] --查找文件路径ps aux | grep [程序名] --查询查询启动状态ps -ef | grep ...
- CentOS 6.5 iso系统定制
前言 更改CentOS6.5背景图片.CentOS标题为DntOS,总之就是用ISO安装或者安装后的系统启动时不能有CentOS标志. ISO光盘目录介绍: (1)isolinux 目录存放光盘启动时 ...