解读es6 class 中 constructor 方法 和 super 的作用

2023-11-03

ES6 的 class 属于一种“语法糖”,所以只是写法更加优雅,更加像面对对象的编程,其思想和 ES5 是一致的。
类和模块的内部,默认就是严格模式,所以不需要使用use strict指定运行模式。

//定义类
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}

等同于

function Point(x, y) {
  this.x = x;
  this.y = y;
}

Point.prototype.toString = function () {
  return '(' + this.x + ', ' + this.y + ')';
};

var p = new Point(1, 2);

其中 constructor 方法是类的构造函数,是一个默认方法,通过 new 命令创建对象实例时,class必须要用new命令创建,不然会报错(TypeError: Class constructor Foo cannot be invoked without ‘new’),自动调用该方法。一个类必须有 constructor 方法,如果没有显式定义,一个默认的 consructor 方法会被默认添加。所以即使你没有添加构造函数,也是会有一个默认的构造函数的。一般 constructor 方法返回实例对象 this ,但是也可以指定 constructor 方法返回一个全新的对象,让返回的实例对象不是该类的实例。

class继承中,子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。

super 这个关键字,既可以当做函数使用,也可以当做对象使用。这两种情况下,它的用法完全不用。

1. 当做函数使用

class A {}
class B extends A {
  constructor() {
    super();  // ES6 要求,子类的构造函数必须执行一次 super 函数,否则会报错。
  }
}

注:在 constructor 中必须调用 super 方法,因为子类没有自己的 this 对象,而是继承父类的 this 对象,然后对其进行加工,而 super 就代表了父类的构造函数。super 虽然代表了父类 A 的构造函数,但是返回的是子类 B 的实例,即 super 内部的 this 指的是 B,因此 super() 在这里相当于 ```A.prototype.constructor.call(this, props)``。

class A {
  constructor() {
    console.log(new.target.name); // new.target 指向当前正在执行的函数
  }
}

class B extends A {
  constructor {
    super();
  }
}
new A(); // A
new B(); // B

可以看到,在 super() 执行时,它指向的是 子类 B 的构造函数,而不是父类 A 的构造函数。也就是说,super() 内部的 this 指向的是 B。

2. 当做对象使用

在普通方法中,指向父类的原型对象;在静态方法中,指向父类。

class A {
  c() {
    return 2;
  }
}

class B extends A {
  constructor() {
    super();
    console.log(super.c()); // 2
  }
}
let b = new B();

上面代码中,子类 B 当中的 super.c(),就是将 super 当作一个对象使用。这时,super 在普通方法之中,指向 A.prototype,所以 super.c() 就相当于 A.prototype.c()。

通过 super 调用父类的方法时,super 会绑定子类的 this。

class A {
  constructor {
    this.x = 1;
  }
  s() {
    console.log(this.x);
  }
}

class B extends A {
  constructor {
    super();
    this.x = 2;
  }
  m() {
    super.s();
  }
}

let b = new B();
b.m(); // 2

上面代码中,super.s() 虽然调用的是 A.prototytpe.s(),但是 A.prototytpe.s()会绑定子类 B 的 this,导致输出的是 2,而不是 1。也就是说,实际上执行的是 super.s.call(this)。
由于绑定子类的 this,所以如果通过 super 对某个属性赋值,这时 super 就是 this,赋值的属性会变成子类实例的属性。

class A {
  constructor {
    this.x = 1;
  }
}

class B extends A {
  constructor {
    super();
    this.x = 2;
    super.x = 3;
    console.log(super.x); // undefined
    console.log(this.x); // 3
  }
}

let b = new B();

上面代码中,super.x 赋值为 3,这时等同于对 this.x 赋值为 3。而当读取 super.x 的时候,调用的是 A.prototype.x,但并没有 x 方法,所以返回 undefined。

注意,使用 super 的时候,必须显式指定是作为函数,还是作为对象使用,否则会报错。

class A {}
class B extends A {
  constructor() {
    super();
    console.log(super); // 报错
  }
}

上面代码中,console.log(super); 的当中的 super,无法看出是作为函数使用,还是作为对象使用,所以 JavaScript 引擎解析代码的时候就会报错。这是,如果能清晰的表明 super 的数据类型,就不会报错。

最后,由于对象总是继承其他对象的,所以可以在任意一个对象中,使用 super 关键字。

参考:http://es6.ruanyifeng.com/#docs/class-extends

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

解读es6 class 中 constructor 方法 和 super 的作用 的相关文章

  • 《SOA 原理•方法•实践》作者毛新生先生签名售书活动

    SOA 原理 方法 实践 作者 毛新生 先生签名售书活动 2007 年8月24日 北京香格里拉 毛新生 先生将在 SOA 架构你的未来 大会现场签名售书 更多详情请访问 http www 900 ibm com cn express kin
  • 快手适合在美妆行业做广告投放吗?快手广告如何计费?

    根据统计数据 化妆品类电商评论中提及短视频声量较去年同期增长367 可见短视视频的广告投放方式深受广大用户喜欢 所以 快手适合做美妆广告吗 我们一起来看一看 一 快手平台适合做化妆品行业的广告吗 由于以下原因 快手很适合做美妆行业的广告投放
  • Deconfounded Visual Grounding

    本文内容仅代表个人理解 如有错误 欢迎指正 1 Background knowledge 这篇论文重度包含因果推理的相关知识 本文可能会粗略带过 感兴趣的可以去看看原论文 有比较详细的解释说明 Q1 什么是confounder confou
  • UIImagePickerController iOS11调起相册 中的照片被导航栏遮挡

    为了适配iOS11下来刷新下下偏移问题 全局设置了 UIScrollView appearance 的ContentInsetAdjustmentBehavior为UIScrollViewContentInsetAdjustmentNeve
  • golang编程cobra-cli库使用

    1 准备 1 1 资源和文档 库 https github com spf13 cobra 文档 https github com spf13 cobra blob master README md 1 2 下载 使用 go get命令下载
  • Centos7升级make和gcc版本到最新

    Background 遇到如下的问题可能就是你make和gcc的版本过低了 需要升级 These critical programs are missing or too old make compiler Check the INSTAL
  • OpenCV之FCN图像分割

    个人主页 风间琉璃 版权 本文由 风间琉璃 原创 在CSDN首发 需要转载请联系博主 如果文章对你有帮助 欢迎关注 点赞 收藏 一键三连 和订阅专栏哦 前言 Fully Convolutional Network FCN 是一种深度学习架构
  • 一文了解各大图数据库查询语言(Gremlin vs Cypher vs nGQL)

    文章的开头我们先来看下什么是图数据库 根据维基百科的定义 图数据库是使用图结构进行语义查询的数据库 它使用节点 边和属性来表示和存储数据 虽然和关系型数据库存储的结构不同 关系型数据库为表结构 图数据库为图结构 但不计各自的性能问题 关系型
  • hibernate 中常用的注解介绍

    定义表名称注解 Entity Table name SYS ROLES schema UAWP Cache usage CacheConcurrencyStrategy NONSTRICT READ WRITE public class R
  • 算法7-6:图的遍历——广度优先搜索(c语言)

    提交 统计 提问 题目描述 广度优先搜索遍历类似于树的按层次遍历的过程 其过程为 假设从图中的某顶点v出发 在访问了v之后依次访问v的各个未曾被访问过的邻接点 然后分别从这些邻接点出发依次访问它们的邻接点 并使 先被访问的顶点的邻接点 先于
  • 【NLP】LSTM总结记录

    目录 前言 RNN 梯度消失和梯度爆炸 梯度裁剪 relu leakyrelu等激活函数 Batch Normalization 批规范化 残差结构 LSTM 长短期记忆网络 LSTM形式 理解LSTM结构 梯度爆炸和消失的解决 pytor
  • MyBatis如何使用 transient 关键字

    MyBatis 是一个持久层框架 用于简化与数据库的交互 在 MyBatis 中 使用 transient 关键字可以标记 Java 对象中的字段 使其在序列化过程中被忽略 在本文中 我们将介绍 MyBatis 的基本用法和如何使用 tra
  • Shell脚本——函数用法

    目录 一 Shell函数的概念 1 Shell函数定义 方法一 方法二 二 函数的返回值 三 函数的传参 四 函数变量的作用范围 五 递归 1 阶乘 脚本命令 操作验证 2 递归目录文件 需求 脚本命令 操作验证 六 函数库 1 建立函数库
  • arxiv网站PDF论文下载速度提升

    arxiv属于国外网站 中国下载网速较慢 推荐使用中科院arxiv的镜像地址 http xxx itp ac cn PDF论文下载速度提升方法 把要访问 arxiv 链接中前面的域名从 https arxiv org 换成 http xxx
  • 花了两天,终于把 Python 的 setup.py 给整明白了

    1 为什么需要对项目分发打包 平常我们习惯了使用 pip 来安装一些第三方模块 这个安装过程之所以简单 是因为模块开发者为我们默默地为我们做了所有繁杂的工作 而这个过程就是 打包 打包 就是将你的源代码进一步封装 并且将所有的项目部署工作都
  • 【华为OD统一考试B卷

    2023年5月份 华为官方已经将的 2022 0223Q 1 2 3 4 统一修改为 2023A卷和2023B卷 你收到的链接上面会标注A卷还是B卷 请注意 根据反馈 目前大部分收到的都是B卷 B卷对应之前专栏的20022部分考题以及新出的
  • 用MATLAB求序列反折

    在这个运算中 x n 以n 0为基准点 以纵轴为对称轴反折得到一个新的序列 即 y n x n 在MATLAB中提供了fliplr函数实现序列反折 fliplr用法是B fliplr A 其中A为矩阵或向量 如果A为矩阵 fliplr函数的
  • 论文笔记: Modeling Extreme Events in Time Series Prediction

    2019 KDD 0 摘要 时间序列预测是数据挖掘中一个深入研究的课题 尽管取得了相当大的改进 但最近基于深度学习的方法忽略了极端事件的存在 这导致将它们应用于实时序列时性能较弱 极端事件是罕见且随机的 但在许多实际应用中确实发挥了关键作用
  • 编写高效的C++程序方法之使用对象池

    对象池技术可以避免在程序的生命期中创建和删除大量对象 如果知道程序需要同一类型的大量对象 而且对象的生命周期都很短 就可以为这些对象创建一个池 pool 进行缓存 只要代码中需要一个对象 就可以向对象池请求 用完此对象时 要把它放回池中 对

随机推荐