代码编织梦想

ES6 入门教程

ECMAScript 6 入门

作者:阮一峰

本文仅用于学习记录,不存在任何商业用途,如侵删

23 Class 的继承

23.5 super 关键字

super这个关键字,既可以当作函数使用,也可以当作对象使用。

在这两种情况下,它的用法完全不同。

【1】第一种情况,super作为函数调用时,代表父类的构造函数。

ES6 要求,子类的构造函数必须执行一次super函数。

class A {}

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

上面代码中,子类B的构造函数之中的super(),代表调用父类的构造函数。这是必须的,否则 JavaScript 引擎会报错。

注意,super虽然代表了父类A的构造函数,但是返回的是子类B的实例,即super内部的this指的是B的实例,因此super()在这里相当于A.prototype.constructor.call(this)

class A {
  constructor() {
    console.log(new.target.name);
  }
}
class B extends A {
  constructor() {
    super();
  }
}
new A() // A
new B() // B

在这里插入图片描述

上面代码中,new.target指向当前正在执行的函数。可以看到,在super()执行时,它指向的是子类B的构造函数,而不是父类A的构造函数。

也就是说,super()内部的this指向的是B

作为函数时,super()只能用在子类的构造函数之中,用在其他地方就会报错。

class A {}

class B extends A {
  m() {
    super(); // 报错
  }
}

上面代码中,super()用在B类的m方法之中,就会造成语法错误。

【2】第二种情况,super作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。

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

class B extends A {
  constructor() {
    super();
    console.log(super.p()); // 2
  }
}

let b = new B();

在这里插入图片描述

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

这里需要注意,由于super指向父类的原型对象,所以定义在父类实例上的方法或属性,是无法通过super调用的。

class A {
  constructor() {
    this.p = 2;
  }
}

class B extends A {
  get m() {
    return super.p;
  }
}

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

上面代码中,p是父类A实例的属性,super.p就引用不到它。

如果属性定义在父类的原型对象上,super就可以取到。

class A {}
A.prototype.x = 2;

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

let b = new B();

在这里插入图片描述

上面代码中,属性x是定义在A.prototype上面的,所以super.x可以取到它的值。

ES6 规定,在子类普通方法中通过super调用父类的方法时,方法内部的this指向当前的子类实例。

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

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

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

在这里插入图片描述

上面代码中,super.print()虽然调用的是A.prototype.print(),但是A.prototype.print()内部的this指向子类B的实例,导致输出的是2,而不是1

也就是说,实际上执行的是super.print.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,所以返回undefined

如果super作为对象,用在静态方法之中,这时super将指向父类,而不是父类的原型对象。

class Parent {
  static myMethod(msg) {
    console.log('static', msg);
  }

  myMethod(msg) {
    console.log('instance', msg);
  }
}

class Child extends Parent {
  static myMethod(msg) {
    super.myMethod(msg);
  }

  myMethod(msg) {
    super.myMethod(msg);
  }
}

Child.myMethod(1); // static 1

var child = new Child();
child.myMethod(2); // instance 2

在这里插入图片描述

上面代码中,super在静态方法之中指向父类,在普通方法之中指向父类的原型对象。

另外,在子类的静态方法中通过super调用父类的方法时,方法内部的this指向当前的子类,而不是子类的实例。

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

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

B.x = 3;
B.m() // 3

在这里插入图片描述

上面代码中,静态方法B.m里面,super.print指向父类的静态方法。

这个方法里面的this指向的是B,而不是B的实例。

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

class A {}

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

上面代码中,console.log(super)当中的super,无法看出是作为函数使用,还是作为对象使用,所以 JavaScript 引擎解析代码的时候就会报错。

这时,如果能清晰地表明super的数据类型,就不会报错。

class A {}

class B extends A {
  constructor() {
    super();
    console.log(super.valueOf() instanceof B); // true
  }
}

let b = new B();

在这里插入图片描述

上面代码中,super.valueOf()表明super是一个对象,因此就不会报错。同时,由于super使得this指向B的实例,所以super.valueOf()返回的是一个B的实例。

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

var obj = {
  toString() {
    return "MyObject: " + super.toString();
  }
};

obj.toString(); // MyObject: [object Object]
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_44226181/article/details/128010893

airbnb javascript 编码规范(涵盖 ecmascript 6+)_mergerly的博客-爱代码爱编程

一份最合理的 JavasScript 编码规范。_ 翻译自: https://github.com/airbnb/javascript 注意:本指南假定您使用的是Babel,并要求您使用 babel-preset-

javascript学习笔记_天道酬勤victor的博客-爱代码爱编程

一、JavaScript基础 什么是JavaScript   JavaScript是一种描述性语言,也是一种基于对象(Object)和事件驱动(Event Driven)的,并具有安全性能的脚本语言。它与HTML(超文本

es6 学习笔记 part3-3_sigmarising的博客-爱代码爱编程

ES6 学习笔记 Part3-3 这是 ES6 学习笔记记录 Part3-3 学习并节选自 阮一峰 - ECMAScript 6 入门 仅供个人学习记录,原著请访问链接 文章目录 ES6 学习笔记 Pa

es6 入门阮一峰这本书的目录_weixin_33851429的博客-爱代码爱编程

2019独角兽企业重金招聘Python工程师标准>>> 第1章 ECMAScript 6简介 1 1.1 ECMAScript和JavaScript的关系 1 1.2 ES6与ECMAScript 2015的关系 1 1.3 语法提案的批准流程 2 1.4 ECMAScript的历史 3 1.5 部署进度 4

前端代码规范 — javascript 风格指南_weixin_30248399的博客-爱代码爱编程

前言 本文基于 github 项目 airbnb/javascript 翻译,也加入了一些个人理解。规范有利于我们更好的提高代码可读性,避免一些不必要的 bug。但是,并没有统一的标准和硬性要求,这里只是给大家提供一些参考,适合团队和自己的才是最好的。 个人博客地址 ?? fe-code 类型 1.1 基本类型 基本类型赋值时

Airbnb JavaScript 编码规范(涵盖 ECMAScript 6+)简版-爱代码爱编程

原文地址:https://www.html.cn/archives/8345#types 1.类型 1.1 基本类型: 当您访问一个基本类型时,您将直接处理它的值。 stringnumberbooleannullundefinedconst foo = 1; let bar = foo; bar = 9; console.log(foo, bar);

前端代码规范整理-爱代码爱编程

前端代码规范 以下内容来源于airbnb,竹春翻译 数据类型 1.1 基本数据类型使用得时候直接进行赋值。 stringnumberbooleannullundefinedsymbolconst foo = 1; let bar = foo; bar = 9; conso.log(foo, bar); // => 1, 9

推荐大家使用的JS代码规范-爱代码爱编程

一种写JavaScript更合理的代码风格。 目录 类型引用对象数组解构字符方法箭头函数模块属性变量比较运算符和等号控制语句注释空白分号类型转换和强制类型转换命名规范事件测试类型 1.1 原始值: 当你访问一个原始类型的时候,你可以直接使用它的值。 stringnumberbooleannullundefinedsymbolconst f

Airbnb JavaScript 风格指南-爱代码爱编程

JavaScript最合理的方法 A mostly reasonable approach to JavaScript 注意: 这个指南假定你正在使用Babel, 并且需要你使用或等效的使用babel-preset-airbnb。 同时假定你在你的应用里安装了带有或等效的airbnb-browser-shims的shims/polyfills

Airbnb JavaScript编码规范指南(ES6)中文版-爱代码爱编程

个人翻译,一些个人见解会用"注:"的形式标出 原版:Airbnb JavaScript Style Guide 最合理的方法书写JavaScript 注意: 本规范假定你在使用 Babel, 并且需要你使用 babel-preset-airbnb 或者等价的工具. 预期你已经在应用中安装了shims/polyfills,和 airbnb-bro

Airbnb JavaScript 代码规范-爱代码爱编程

其他代码风格指南 ES5 (Deprecated)ReactCSS-in-JavaScriptCSS & SassRuby目录 类型引用对象数组解构字符方法箭头函数类和构造器模块迭代器和发生器属性变量提升比较运算符和等号块控制语句注释空白逗号分号类型转换和强制类型转换命名规范存取器事件jQueryECMAScript 5 兼容性ECMAScri

前端开发js编码规范问题-爱代码爱编程

在页面开发中,基本每个人都有自己的开发习惯,这就导致在多人开发时,我们很多时候会因为不习惯他人的开发习惯,导致代码的阅读很难,拖慢开发进度,或者是直接无法进行维护。所以,一个良好的编码习惯是我们应该养成的,这会使得我们自己的开发速度变快的同时增加代码的可阅读性。 这里我搬运来了github上面的一篇文章,希望能对大家有帮助。无疑,这对我自己也有很大的帮助原

前端知识点部分总结-爱代码爱编程

1.怪异盒模型 标准盒模型:在标准模式下,一个块的总宽度 = 内容的width + padding(左右) + border(左右) + margin(左右) 怪异盒模型:一个块的总宽度 = 内容的width + margin(左右)(这里的width包含了padding(左右)和border(左右)的值) 2.vuex状态管理工具 state:仓

es6学习_抢占有利地形的博客-爱代码爱编程

1.使用let声明变量 let 之间互不影响,使用 for 循环for(let i=0;i<arr.length;i++){}会生成多个 let 给多个作用域使用,互不影响。 2.const声明变量 3.解

【vue.js】使用高德地图选择省市区后,再点击确认当前选择的位置_萌村村花杨小花的博客-爱代码爱编程

成品展示 前期准备 先去高德开放平台申请一个web端的key。 2022年后申请的key,必须和它生成的secret一起使用。 可使用服务选择web端 在vue项目中,可以通过直接引入js文件,也可以安装vu

[前端基础] javascript 进阶篇-爱代码爱编程

封装 Ajax ajax 可以无需刷新页面与服务器进行通讯,允许根据用户事件来更新部分页面内容。 readyStatus 的值: 0:未初始化1:启动;已经调用open()方法,但尚未调用send()方法。2:发送;已