2022-03-15 [总结]JS继承的常见几种方式和优缺点:原型链继承,构造函数继承,组合继承,原型式继承,寄生式继承,寄生组合式继承,class继承

本文主要是介绍2022-03-15 [总结]JS继承的常见几种方式和优缺点:原型链继承,构造函数继承,组合继承,原型式继承,寄生式继承,寄生组合式继承,class继承,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

        • 0.object.create
      • 分类一:不使用Object.create的继承
        • 1.原型链继承
          • 原理:给原型对象增加一层指向
          • 优缺点
          • 格式和示例
        • 2.构造函数继承
          • 原理:使用bind改变某个功能的this指向从而实现继承
          • 优缺点
          • 格式和示例
        • 3.组合继承(原型链+构造函数)
          • 原型链继承和构造函数继承的缺点
          • 组合继承的原理改变this指向+原型对象
          • 优缺点
          • 语法和示例
      • 分类二:使用Object.create的继承
        • 4.原型式继承
          • 定义
          • 优缺点
          • 语法和示例:原型式继承是浅拷贝
          • 使用Object.create进行原型式继承
        • 5.寄生式继承
          • 定义
          • 语法和实例
        • 6.寄生组合式继承(原型式+寄生式)
          • 定义
          • 基本思路
          • 优缺点:这是一种完美的继承方式。
          • 语法和示例(重要)
          • 参考文章
      • 分类三:class继承
        • 7.ES6的class继承
          • 步骤
          • 为什么必须要调用super方法?
          • 为什么super函数要放在最上面?
          • 语法与示例

0.object.create

2022-03-14 Object.create的定义和用法,Object.create和new的区别
在这里插入图片描述

分类一:不使用Object.create的继承

1.原型链继承
原理:给原型对象增加一层指向
优缺点
  • 优点:既能继承构造函数又能继承原型对象
  • 缺点:消耗性能,增加读取时间;对参数的处理不友好,即不方便传参(若一个实例修改原型属性的值,则所有实例上的值都会改变)
格式和示例
/*目的:让Child的实例获得name属性和say()方法*/
// 构造函数Person
function Person() {this.name = 'zs';}
// 构造函数的原型上的方法
Person.prototype.say = function() { return "hello";};
// 1.原型链继承:将父类型的实例指向子类型的原型
function Child() {}
Child.prototype = new Person();
var c = new Child();
console.log(c.name, c.say());//zs hello
2.构造函数继承
原理:使用bind改变某个功能的this指向从而实现继承
优缺点
  • 优点:简单方便,可以实现多继承
  • 缺点:只能继承构造函数,不能继承原型
格式和示例
// 构造函数Person
function Person() {this.name = 'zs';}
// 构造函数的原型上的方法
Person.prototype.say = function() { return "hello";};
// 2.构造函数继承:通过将Person的this改成Child的this,来实现继承Person的属性与方法
function Child() {Person.bind(this)();}
var c = new Child();
console.log(c.name, c.say()); //zs 报错:不能继承构造函数的原型上的方法
3.组合继承(原型链+构造函数)
原型链继承和构造函数继承的缺点
  • 原型链继承的缺点:引用类型的原型属性会被所有的实例共享
  • 构造函数继承的缺点:不能继承原型
组合继承的原理改变this指向+原型对象

即:

  • 使用call/apply继承父类构造器上的内容
  • 使用原型继承来继承父类的原型
优缺点
  • 优点:既能继承构造函数又能继承原型对象,可以实现多继承,传承方便,没有增加原型链
  • 缺点:对参数的修改不友好(在继承parent的同时传参)
语法和示例
// 构造函数Person
function Person() {this.name = 'zs';}
// 构造函数的原型上的方法
Person.prototype.say = function() { return "hello";};
// 3.组合继承:使用call/apply继承父类构造器上的内容,使用原型继承来继承父类的原型
function Child() {}
Person.bind(this)();//用于继承构造函数上的属性
Child.prototype = new Person();//用于继承原型上的方法
var c = new Child();
console.log(c.name, c.say()); //zs hello

分类二:使用Object.create的继承

4.原型式继承
定义

原型式继承本质其实就是个浅拷贝,以一个对象为模板复制出新的对象

优缺点
优点:父类方法可以复用。
缺点:父类的引用属性会被所有子类实例共享子类构建实例时不能向父类传递参数
语法和示例:原型式继承是浅拷贝
/*原型式继承*/
function yuanxing(o) { //yuanxing是一个封装原型式继承的函数function G() {} //G是构造函数G.prototype = o; //把o作为构造函数G的原型对象return new G(); //返回一个构造函数new出来的实例对象
}
/*原型对象*/
var obj = { //obj作为原型对象skills: ['html', 'css']
};
/*实例对象*/
var obj1 = yuanxing(obj); //调用封装函数,进行原型式继承,并把G()new出来的实例对象赋给obj1==>如此,obj上的skills方法就被obj1继承
// 证明原型式继承是浅拷贝
var obj2 = yuanxing(obj);
obj2.skills.push("javascript");
console.log(obj1.skills); // ['html', 'css', 'javascript']
使用Object.create进行原型式继承
/*原型式继承*/
function yuanxing(o) { //yuanxing是一个封装原型式继承的函数function G() {} //G是构造函数G.prototype = o; //把o作为构造函数G的原型对象return new G(); //返回一个构造函数new出来的实例对象
}
/*原型对象*/
var obj = { //obj作为原型对象skills: ['html', 'css']
};
/*实例对象*/
var obj1 = yuanxing(obj); //调用封装函数,进行原型式继承,并把G()new出来的实例对象赋给obj1==>如此,obj上的skills方法就被obj1继承
// 证明原型式继承是浅拷贝
var obj2 = yuanxing(obj);
obj2.skills.push("javascript");
console.log(obj1.skills); // ['html', 'css', 'javascript']
//使用ES5新增的Object.create方法进行原型式继承<==不使用封装函数yuanxing
var obj3 = Object.create(obj);
obj3.skills.push("jQuery");
console.log(obj1.skills, obj3.skills); //4) ['html', 'css', 'javascript', 'jQuery']  4) ['html', 'css', 'javascript', 'jQuery']
5.寄生式继承
定义

寄生式继承就是将原型式继承再次封装,然后在对象上拓展新的方法,最后再把新对象返回

语法和实例
/*原型式继承*/
function yuanxing(o) { //yuanxing是一个封装原型式继承的函数function G() {} //G是构造函数G.prototype = o; //把o作为构造函数G的原型对象return new G(); //返回一个构造函数new出来的实例对象
}
/*寄生式继承*/
function jisheng(yObj) { //寄生式继承的步骤:var sObj = yuanxing(yObj); //step1:原型式继承:以yObj为原型对象,创建一个实例对象sObjsObj.say = function() { //step2:给这个新对象扩展新方法return `我的前端技能有:${this.skills}`; };return sObj;//step3:返回这个新对象
}
/*原型对象*/
var obj = { //obj作为原型对象skills: ['html', 'css']
};
/*实例对象*/
var obj1 = yuanxing(obj); //调用封装函数,进行原型式继承,并把G()new出来的实例对象赋给obj1==>如此,obj上的skills方法就被obj1继承
// 证明原型式继承是浅拷贝
var obj2 = yuanxing(obj);
obj2.skills.push("javascript");
console.log(obj1.skills); // ['html', 'css', 'javascript']
//使用ES5新增的Object.create方法进行原型式继承<==不使用封装函数yuanxing
var obj3 = Object.create(obj);
obj3.skills.push("jQuery");
console.log(obj1.skills, obj3.skills); //4) ['html', 'css', 'javascript', 'jQuery']  4) ['html', 'css', 'javascript', 'jQuery']
// 调用寄生式继承的封装函数
var obj4 = jisheng(obj);
console.log(obj4.say());//我的前端技能有:html,css,javascript,jQuery
6.寄生组合式继承(原型式+寄生式)
定义

通过借用构造函数来继承属性,
通过原型链的混成形式来继承方法。

基本思路

不必为了指定子类型的原型,而调用超类型的构造函数,我们所需要是超类型原型的一个副本而已。
本质上是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型

优缺点:这是一种完美的继承方式。

寄生组合继承:可以解决组合继承会调用两次父类的构造函数,造成浪费的问题
因此避免了在原型上面创建多余的属性。
与此同时,原型链还能保持不变;
因此,还能正常使用instanceof和isPropertyOf()

语法和示例(重要)
// 1.定义父类型
function Person(name) {this.name = name;this.legNum = 2;
}
Person.prototype.sayHello = function() {console.log(`我叫${this.name}`);
};
// 2.定义继承方法
function inherit(subType, superType) {// 在new inheritFn时,将构造函数指向子类function inheritFn() {this.constructor = subType;}inheritFn.prototyp = superType.prototype;// 将子类的原型指向父类原型的一个副本subType.prototype = new inheritFn();
}
// 3.定义子类并实现继承
// 定义子类构造函数Son
function Son(name, age) {Person.call = (this, name); //借用构造函数this.age = age;
}
// 将子类Son的原型指向父类原型的一个副本
inherit(Son, Person); //注意:要执行该动作以后,才能在Son.prototype上定义方法
// Son的Prototype上定义sayAge方法
Son.prototype.sayAge = function() {console.log(`我今年${this.age}`);
};
// 定义另一个子类构造函数Daughter
function Daughter(name, sex) {Person.call(this, name); //借用构造函数this.sex = sex;
}
// 将子类Daughter的原型指向父类原型的一个副本
inherit(Daughter, Person);
// Daughter的Prototype上定义saySex方法
Daughter.prototype.saySex = function() {console.log(`我是${this.sex}`);
};
// 4.输出结果
var s = new Son("李雷", 12);
console.log(s);
s.sayHello();
s.sayAge();
var d = new Daughter("韩梅梅", "女");
console.log(d);
d.sayHello();
d.saySex();
参考文章

https://blog.csdn.net/qq_42451979/article/details/125271820

分类三:class继承

7.ES6的class继承
步骤
  • class通过关键字extends实现继承
  • 子类在constructor方法中调用super方法
为什么必须要调用super方法?

这是因为这里的继承是先塑造父类,再塑造子类。
也就是先将父类的东西都拿过来之后,再进行子类的添加。
而super负责的就是将父类的东西拿过来。所以必须先调用super。

为什么super函数要放在最上面?

class的继承是先将父类拿过来再进行子类的添加,
如果想要给自身添加属性和方法,需要在调用call或者apply之后添加。
否则如果存在同名属性,后面的会覆盖前面的。

语法与示例
class Person {constructor(name, age) {this.name = namethis.age = age}say() {console.log('你好')}
}
class Son extends Person {
}
const s = new Son()
s.say() // 你好

这篇关于2022-03-15 [总结]JS继承的常见几种方式和优缺点:原型链继承,构造函数继承,组合继承,原型式继承,寄生式继承,寄生组合式继承,class继承的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/221137

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

hdu4869(逆元+求组合数)

//输入n,m,n表示翻牌的次数,m表示牌的数目,求经过n次操作后共有几种状态#include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdlib.h>#includ

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

内核启动时减少log的方式

内核引导选项 内核引导选项大体上可以分为两类:一类与设备无关、另一类与设备有关。与设备有关的引导选项多如牛毛,需要你自己阅读内核中的相应驱动程序源码以获取其能够接受的引导选项。比如,如果你想知道可以向 AHA1542 SCSI 驱动程序传递哪些引导选项,那么就查看 drivers/scsi/aha1542.c 文件,一般在前面 100 行注释里就可以找到所接受的引导选项说明。大多数选项是通过"_

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

webm怎么转换成mp4?这几种方法超多人在用!

webm怎么转换成mp4?WebM作为一种新兴的视频编码格式,近年来逐渐进入大众视野,其背后承载着诸多优势,但同时也伴随着不容忽视的局限性,首要挑战在于其兼容性边界,尽管WebM已广泛适应于众多网站与软件平台,但在特定应用环境或老旧设备上,其兼容难题依旧凸显,为用户体验带来不便,再者,WebM格式的非普适性也体现在编辑流程上,由于它并非行业内的通用标准,编辑过程中可能会遭遇格式不兼容的障碍,导致操