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 ...
随机推荐
- 【C++】数组中的第k个最小元素
分治思想求解的问题,但是比较特殊,只有分解问题和求解小问题,不需要合并 每次也只需要经过判断,分解一半,所以比其他分解两边的效率高 最坏情况时间复杂度为O(n^2),期望时间复杂度为O(n) 找基准值 ...
- mfc c++优化
1.不住求精度时,尽量使用单精度浮点型2.使用32位数据类型3.使用有符号和无符号整型: 前提:无需考虑正负时 double x; int i; x = i; 使用有符号:unsigned int i ...
- 红黑树、TreeMap、TreeSet
事先声明以下代码基于JDK1.8版本 参考资料 大部分图片引自https://www.jianshu.com/p/e136ec79235c侵删 https://www.cnblogs.com/skyw ...
- odoo13之右上角弹出提示框
前言 在odoo中已经提供好了右上角弹出提示框的接口,我们只需要调用即可: 而提示框的实现又分为前端js实现和后段函数实现,前后端实现的效果相同. 实现效果图 前端实现提示框 在前端中显示提示框最常用 ...
- WriteFile,CreateFile,ReadFile
原文链接:https://blog.csdn.net/Jeanphorn/article/details/44982273 将数据写入一个文件.该函数比fwrite函数要灵活的多.也可将这个函数应用于 ...
- spring aop 、Redis实现拦截重复操作
一.问题:项目中有一些重复操作的情况,比如: 1.从场景有用户快速点击提交按钮,或者postMan测试时快速点击 2.从业务上来说,用户注册.用户下单等 3.黑客攻击 二.解决办法 1.使用sprin ...
- 等待多线程完成的CountDownLatch(带示例)
开始磨刀霍霍向多线程了,这期是 CountDownLatch 的一个小示例. 定义:CountDownLatch 允许一个或多个线程等待其他线程完成操作. 应用需求举例:假设有4个线程,A.B.C.D ...
- Windows平台部署Asp.Net Core应用
一. 简介 Asp.Net Core 部署方式有两种:依赖框架和独立部署. 1. 框架依赖的部署: 顾名思义,依赖框架的部署 (FDD) 依赖目标系统上存在共享系统级版本的 .NET Core. 由于 ...
- moviepy音视频开发:使用volumex调节音量大小及其花式用法
☞ ░ 前往老猿Python博文目录 ░ 一.概述 音频数据的音量体现为声音的振幅,振幅越大则声音越大,具体到音频帧数据上,体现为声音的绝对值越大则振幅越大音量越大,调节音量大小的本质是调整帧数据的绝 ...
- Asp.NetCore之AutoMapper进阶篇
应用场景 在上一篇文章--Asp.NetCore之AutoMapper基础篇中我们简单介绍了一些AutoMapper的基础用法以及如何在.NetCore中实现快速开发.我相信用过AutoMapper实 ...