js系列-class类,继承

类继承底层原理:从 JavaScript 引擎视角剖析 摘要: 本文深入解析JavaScript类继承的底层原理。首先介绍ES5原型链继承的实现方式,通过构造函数与原型链的关联实现继承,但存在引用属性共享和传参受限的缺陷。随后分析ES6的class和extends语法,其本质是原型链的语法糖,通过super调用父类逻辑并支持静态方法继承。两种继承方式均基于原型链机制,ES6的类继承提供了更简洁规范的语法,理解其原理有助于开发者高效运用继承特性。 阅读详情

为什么要学习类

每一个新技术,新概念的产生,都是为了解决之前的问题,在没有类之前我们用构造函数模拟类,先定义构造函数,再往构造函数原型prototype上增加方法,书写复杂,没有整体性,而类会让你体验真正面向对象编程。

类

是一种特殊的函数,本质还是原型和构造函数的概念。

定义类

声明定义

class Person { }
//类本质是函数
console.log(typeof Person);//function

表达式定义

let p = class { }

和函数不同点

不会提升

//定义之前调用报错
console.log(Person);//ReferenceError: Cannot access 'Person' before initialization
class Person { }

//而函数可以
console.log(People);//ƒ People() { }
function People() { }

是块作用域

{
  class Person { }
  function People() { }
}
console.log(People);//ƒ People() { }
console.log(Person);//ReferenceError: Cannot access 'Person' before initialization

类方法之间不能加逗号

class Person {
  constructor() { }
  run() {
    console.log('run');
  }
  jump() {
    console.log('jump');
  }
}

类的构成

类中包含构造函数,实例属性, 静态属性,原型方法,静态方法,获取函数,设置函数。下面我们分别道来。

class Person {
  //实例属性
  age = 20
  hobby = ['看书', '打球']
  //静态属性
  static memo = '静态属性'
  //构造函数
  constructor(target) {
    //实例属性
    this.target = target;
  }
  //原型方法
  run() {
    console.log('run');
  }
  // 静态方法
  static createPerson(target) {
    return new Person();
  }
  //设置函数
  set weight(num) {
    this._weight = num;
  }
  //获取函数
  get weight() {
    return this._weight;
  }
}
console.dir(Person);
let snail = new Person('MrSnail');
console.log(snail);

类构造函数

即类中constructor函数,如果不定义,类会设置默认constructor函数。即: 

  class Person { }
  //等价于
  class Person {
    constructor() { }
  }

   构造函数的作用是用来实例化对象的。类实例化时传入的参数会用作构造函数参数

class Person {
  constructor(target) {
    this.target = target;
  }
}
new Person('snail');

类构造函数其实没什么好讲的,但构造函数中属性,即实例属性,我们要好好看看:

实例属性

class Person {
  //实例属性
  hobby = ['看书', '打球']
  age = 20
  constructor(target) {
    //实例属性
    this.target = target;
  }
}
console.dir(new Person('MrSnail'))

我们看到,实例上面有了上面定义的三个属性,那这里就有个疑问了,定义在constructor中的实例属性和直接定义在类中的实例属性有什么不同呢?

target是定义在constructor里的实例属性,age和hobby是在类中的实例属性。

不同点:constructor里面定义的target我们实例化的时候可以传值,而age和hobby是常量,不能传值。

相同点:都是实例属性,每个实例上都单独保存一份,age=20等价于this.age=20,hobby也是如此,他们都挂载在this上,而不是原型上。

静态属性

class Person {
  //实例属性
  age = 20
  //静态属性
  static memo = '静态属性'
  constructor(target) {
    //实例属性
    this.target = target;
  }
}
console.dir(Person);
console.dir(new Person('MrSnail'))

通过观察我们发现静态属性是类上的属性,不会出现在实例中。

原型方法

class Person {
  //实例属性
  age = 20
  constructor(target) {
    //实例属性
    this.target = target;
  }
  //原型方法
  run() {
    console.log('原型方法')
  }
}
let snail = new Person('MrSnail')
snail.run()//原型方法
console.dir(snail);

静态方法

静态方法有个很重要的作用就是,可以用来生成实例

class Person {
  //实例属性
  age = 20
  constructor(target) {
    //实例属性
    this.target = target;
  }
  //原型方法
  run() {
    console.log('原型方法')
  }
  // 静态方法
  static createPerson(target) {
    return new Person();
  }
}
//以往我们生成实例
let snail = new Person('MrSnail')
//使用静态方法
let snail2 = Person.createPerson('MrSnail');

使用静态方法生成实例似乎更优雅

获取函数和设置函数

和对象get,set使用方式一样

class Person {
  //实例属性
  age = 20
  constructor(target) {
    //实例属性
    this.target = target;
  }
  //设置函数
  set weight(num) {
    if (num > 200) {
      throw new Error('数据不合格')
    }
    this._weight = num;
  }
  //获取函数
  get weight() {
    return this._weight;
  }
}
let snail = new Person('MrSnail');
console.dir(snail)
snail.weight = 300//Error: 数据不合格

类实现继承

我们上篇文章讲,通过原型链实现继承(上篇:js系列-原型和原型链继承)。虽然类实现继承本质还是原型链,但书写方式更优雅:

class Person {
  constructor(target) {
    this.target = target;
  }
  run() {
    console.log('Person中run方法');
  }
}
class Snail extends Person {
  constructor(target) {
    super(target);
  }
}
let snail = new Snail('snail');
console.log(snail.target)//snail
snail.run();//Person中run方法
console.dir(snail);

不仅可以继承一个类,也可以继承普通构造函数

function Person(target) {
  this.target = target;
}
Person.prototype.run = function () {
  console.log('Person中run方法');
}
//继承普通构造函数
class Snail extends Person {
  constructor(target) {
    super(target);
  }
}
let snail = new Snail('snail');
console.log(snail.target)//snail
snail.run();//Person中run方法

super

在子类中通过super调用原型属性方法。在子类constructor不要在调用super()之前引用this

class Person {
  static age = 20;
  static jump() {
    console.log("Person中静态方法jump");
  }
  perRun() {
    console.log("Person中的run方法");
  }
}
class Snail extends Person {
  run() {
    super.perRun();
    //下面调用会报错,只能在子类静态方法中通过super调用父静态方法
    // super.jump();
  }
  static inRun() {
    super.jump();
  }
}
let snail = new Snail();
snail.run();

注意点:

super可以在派生类(子类)的构造函数,方法,静态方法中使用,参考上面代码。

父类中的静态方法只能在子类的静态方法中通过super调用,不可在子类其他方法中调用。

super可以像构造函数一样,手动传参。

如果在子类中没写constructor构造函数,类内部会默认构造函数,并调用super()。

在子类构造函数中,不能在调用super()之前引用this。

mixin混入

即一个类继承多个类

class Person { }

let extendA = (Superclass) => class extends Superclass {
  aRun() {
    console.log('aRun');
  }
}
let extendB = (Superclass) => class extends Superclass {
  bRun() {
    console.log('bRun');
  }
}
let extendC = (Superclass) => class extends Superclass {
  cRun() {
    console.log('cRun');
  }
}

function mix(BaseClass, ...Mixins) {
  return Mixins.reduce((total, item) => item(total), BaseClass)
}

class Snail extends mix(Person, extendA, extendB, extendC) { }
let snail = new Snail();
snail.aRun()
snail.bRun()
snail.cRun()

 

JavaScript基础教程|Class 基本语法,类继承extends 所以,class 到底是什么?正如人们可能认为的那样,这不是一个全新的语言级实体。让我们揭开其神秘面纱,看看类究竟是什么。这将有助于我们理解许多复杂的方面。在 JavaScript 中,类是一种函数。// 佐证:User 是一个函数class User {…} 构造实际上做了如下的事儿:创建一个名为 User 的函数,该函数成为类声明的结果。该函数的代码来自于 constructor 方法(如果我们不编写这种方法,那么它就被假定为空)。 阅读详情

相关推荐

【嵌入式面经】上海 70迈 线上笔试

“关注|点赞|收藏” 福利干货第一时间送达!最近在做免费的嵌入式知识分享,帮助对嵌入式感兴趣的同学学习嵌入式、做项目、找工作!

qq_56921854的博客 1135

js--继承

1. 原型链继承 将父类的实例作为子类的原型 function Parent(){ this.isShow=ture; this.info={ name:"hh", age:14, } } Parent.prototype.getInfo=function(){ console.log(this.isShow); console.log(this.info); } function Child(){}; Child.pr

qq_43654065的博客 719

三轴云台稳定控制算法优化实战:从PID到模糊自适应

本文深入探讨了三轴云台稳定控制算法的优化实践,从经典PID控制到模糊自适应算法的进阶应用。通过实战案例和代码示例,详细解析了PID调参技巧、模糊控制实现及多传感器数据融合方法,帮助工程师在复杂环境下提升云台抗干扰能力和响应速度,特别适用于无人机航拍等场景。

green的博客 908

JavaScript Class类详解

ECMAScript 6 提供了更接近传统语言的写法,新引入的class关键字具有正式定义类的能力。类(class)是ECMAScript中新的基础性语法糖结构,虽然ECMAScript 6类表面上看起来可以支持正式的面向对象编程,但实际上它背后使用的仍然是原型和构造函数的概念,让对象原型的写法更加清晰、更像面向对象编程的语法。

m0_37824255的博客 2万+

Ubuntu桌面消失?可能是lightdm配置在捣鬼:详细解析/etc/lightdm.conf的优先级机制与实战修复

本文详细解析了Ubuntu系统因lightdm显示管理器配置错误导致桌面消失的问题。通过分析/etc/lightdm.conf的优先级加载机制,提供了从systemctl诊断、调试模式运行到实战修复配置语法错误(如缺失[Seat:*]组)的完整方案。文章还探讨了在系统无法启动时使用chroot或恢复模式进行高级救援,并对比了lightdm与gdm3在NVIDIA驱动环境下的不同表现,帮助用户高效恢复图形界面。

weixin_29313547的博客 420

深入解析Mifare Classic Crypto1认证流程与密钥交换机制

本文深入解析Mifare Classic Crypto1认证流程与密钥交换机制,详细介绍了Crypto1加密算法的工作原理、认证初始化阶段、随机数交换与密钥流生成过程,以及双向验证步骤。文章还分析了Mifare Classic的安全漏洞,包括随机数生成缺陷和密钥流恢复攻击,并提供了Proxmark3实战演示和防护建议。

c6d7e8f9g的博客 898

JavaScript中class类的三种方法详解(静态方法、普通方法与构造方法)

在js的类中,可分为三种方法,constructor构造方法、静态方法与普通方法。 一、constructor构造方法 1.概念 类的作用在于构建对象,而constructor构造方法就是用于构建对象实例。 2.使用方法 在使用new关键字生成对象时,constructor方法会被执行,最终return的结果就是生成的对象实例。 当一个类没有constructor方法时会自...

momDIY的博客 1万+

Rockchip RK3566 Buildroot SDK构建与内核编译实战指南

嵌入式Linux开发中,交叉编译环境是系统启动的基础支撑。Buildroot作为轻量级嵌入式构建框架,通过配置驱动、自动化下载和分层编译机制,显著降低定制化Linux发行版的集成门槛。其核心价值在于将内核、根文件系统与工具链统一管理,兼顾资源约束下的确定性构建与工程可复现性。典型应用场景涵盖ARM64平台(如RK3566)的固件开发、IoT设备量产镜像生成及硬件Bring-up阶段的快速验证。本文围绕Buildroot SDK全流程实践,深入解析环境搭建、Repo源码同步、离线DL库预置及内核编译等关键环节

weixin_36047538的博客 134

js高级(原型继承与原型链,类(实例成员,静态成员),constructor(接收参数),extends(继承),严格模式,指定this的值)

原型继承 定义:具体是指一个对象可以将另一个对象的属性或方法继承过来(占为已有) (原型继承是通过原型对象来实现继承的功能) 原型链 定义:原型链其实就是构造函数的原型“串联”一起(多个存在继承关系的对象之间原型对象的查找关系) 在JavaScript 对象中包括了一个非标准备的属性__proto__ 它指向了构造函数的原型对象,通过它可以清楚的查看原型对象的链状结构。 类 定义:类是一个代码结构,主要作用是创建对象 (类 是专门用来造对象的(类的作用和构造函数的作用一致,都是用来造对象的) 语法:c

weixin_69749948的博客 1205

2022年灌溉试验设计与数据分析考试试题

2.表2数据为表层0~10cm的原状土离心机土壤水分特征曲线试验数据,(1)请利用R语言nls函数通过Van Genuchten方程对土壤体积含水率和土壤基质势进行拟合;(3)指明土壤基值势为-33 kPa和-1500kPa时的体积含水率。1.请根据表1数据,以灌溉模式为主区,生物炭用量为子区,利用R语言agricolae包生成裂区试验设计试验处理布置图;3.以R工具包factoextra中decathlon2数据集前10列为数据进行PCA分析,要求计算出(1)前5个主成分的特征值、特征向量;

Mrrunsen的博客 265

KEPServerEX物联网网关(IoT Gateway)REST客户端代理(非原创)

(中文版)资料来源于【OPC-KEPServerEX学习KEPWare交流】905485143群的【455196383】【零下一度】 一。KEPServerEX物联网网关REST客户端代理演示 在KSE中,首先构建一个带有通道/设备/标签的模拟器系统。 例如,下面是三个随机项目。 直接到IoT网关插件,添加新代理。 从类型列表中选择REST Client。 终结点...

-雲飛兄-博客 5805

js中的类和函数传参的方式

https://www.bilibili.com/video/BV1vJ411k7ZP?p=2&spm_id_from=pageDriver&vd_source=90a9c7618953f5d275200b2fa7aed461

liulang68的博客 797

【Python高阶开发】12. 工业知识图谱实战:从0构建设备故障诊断系统(附Neo4j部署+完整代码)

摘要:传统工业设备故障诊断依赖专家经验,存在知识难沉淀、故障定位慢、根因分析不彻底等痛点。本文基于开源工具栈(Neo4j+Py2neo+Spacy+FastAPI),从0到1构建工业知识图谱故障诊断系统。内容涵盖:知识图谱核心概念解析、Neo4j图数据库部署、工业设备本体设计、多源知识抽取(结构化Excel+非结构化手册)、图谱构建与查询、故障诊断与根因分析功能实现,以及可视化与API服务部署。每个模块附完整可运行代码及执行结果,新手可按步骤复现全流程,进阶读者可直接复用代码到实际项目

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 1106

详细了解JavaScript中的class类

JavaScript中的class类介绍,带你学习class类的使用,简单介绍几个例子和使用时注意事项。

m0_67584973的博客 413

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

JS中Class类的继承

Class继承     Class 可以通过 extends 关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多 class Animate { constructor() { // 默认返回实例对象 this } } class Dog extends Animate { constructor() { super() } }     子...

关注最新技术问题并持续维护更新 5364

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

js中的class类

这是es6的新特性,用于实现面向对象的编程 1.class类的创建 创建一个class类 class myClass{ //构造器,默认为空的构造器 //当class在被new时就会调用构造器 //相当于function //function myClass(name,age){ // this.name=name // this.age=age //} constructor...

程序员徐小白的博客 1万+

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

js 总结ES6中Class以及继承

一、Class 1、ES6中的class可以看作是一个语法糖,它的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰,更加面向对象编程的语法而已。 class Point { // 定义一个Point类 constructor(x,y){ // 构造方法 this.x=x; this.y=y; } // =...

qq_37473645的博客 1万+

js继承 - class的继承

和之前讲的js的继承方式不同,class的继承是es6里面才有的。在讲class的继承之前,需要先了解一下class: class的基本语法 class,也就是我们常说的类, // class class Person { constructor(name, age) { this.name = name this.age = age } sayName() { console.log(this.name) } } const p1 = new Person('p1'

piaojiancong的博客 7632

js中es6 class类的继承

js中 es6 class类的继承 语法 // 父类 class Father{ } // 子类继承父类 class Son extends Father { } 子类使用super关键字访问父类的方法 //定义了父类 class Father { constructor(x, y) { this.x = x; this.y = y; } sum...

清风的博客 1808

【javascript】js中关于Class(类)的介绍和使用

类语法有两个组成部分:类表达式和类声明。类声明和类表达式的主体都执行在严格模式下。比如,构造函数,静态方法,原型方法,getter 和 setter 都在严格模式下执行。一个类的类体是一对花括号/大括号 {} 中的部分。这是你定义类成员的位置,如方法或构造函数。constructor方法是一个特殊的方法,这种方法用于创建和初始化一个由class创建的对象。一个类只能拥有一个名为“constructor”的特殊方法。如果类包含多个constructor的方法,则将抛出 一个SyntaxError。

qq_2511276124的博客 2748

Javascript中class类的用法以及继承

什么是类? 类是面向对象编程语言的通用结构。 类是一种结构:将现实世界中存在的关系,采用一种{}的形式,将各种数据和数据的操作捆绑到一起:外界不需要知道里面到底是怎么实现的,只需要调用里面提供的可操作的方法(封装)。 比原型方式要简洁的多,结构层面更加清晰。 语法操作: 1.类class是ES6的语法 2.类的语法:class 类名 {} 3.类名不能重复 实例化 4.类不会自动运行:需要new的时候才会触发 5.只要对象产生:new出一个对象:里面的构造器就会被触发 方法实现 6.类里面的方法:方.

l13640698113的博客 2201

深入理解 JavaScript 中 class 的基本语法与继承机制

在JavaScript中,我们可以通过 class 关键字来定义类。在上述代码中,Person 就是我们定义的类,类内部有一个 constructor 构造函数(下一小节会详细介绍它),用于初始化类的实例属性。const person1 = new Person('张三', 20);const person2 = new Person('李四', 25);这里,person1 和 person2 就是 Person 类的两个不同实例,它们各自拥有独立的属性值。

yan1915766026的博客 1992

JavaScript Class类 | 类的继承 - 类的使用 -原型与原型链

有一种说法解释: 因为构造器是用来对实例初始化的,而子类实例在初始化之前要先初始化它的父类成分。因为 JS 是弱类型的,super 调用时的传参没法自动预判,没法代劳。Parent.call(this,name) 第一次参数是指定函数Parent里的this 为参数this,name为Parent函数传递的参数。存在暂时性死区,代码执行过程中的一段时间内,在此期间无法使用标识符,也不能引用外层作用域的变量。实例原型链:子类的实例可以拥有父类的方法,通过。作用:创建一个新对象,新对象的隐式原型指向参数。

好好学习天天向上 1319

js中class继承和super

js中class继承和super1.class的简单介绍2.class的继承 1.class的简单介绍 先看一段构造函数的代码 function Person(name,age) { this.name = name; this.age=age; } Person.prototype.say = function(){ return "我的名字叫" + this.name...

nightwishh的博客 4416

JS——ES6 class类和继承及其实际运用

JS——ES6 class类和继承 1、类的定义 2、类的构造函数和其他属性 3、类的继承

偷只猫来养的博客 1672

JavaScript 类继承

构造函数是JavaScript类中的一个重要组成部分,它负责初始化类的实例。在ES6中,构造函数使用constructor关键字定义,位于类定义的顶部。构造函数的主要职责是为新创建的对象设置初始状态,分配必要的资源,并执行任何必需的初始化操作。

2401_86544677的博客 930
上一篇: js系列-原型和原型链继承
下一篇: js系列-modul模块
前端蜗牛君
博客等级 码龄10年 274粉丝 158原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值