你真的了解[super ]关键字吗?
前言
此篇文章是看了阮老师的es6教程,看到super
关键字的时候觉得有必要总结梳理一下,原文还是参考 ECMAScript 6入门。
正文
super
这个关键字,既可以当作函数使用,也可以当作对象使用。
1.当作函数使用
super
作为函数调用时,代表父类的构造函数。ES6
要求 ,子类的构造函数必须执行一次super
函数。
即作为 函数
使用时下面的代码时 固定使用套路
:
class A {
constrctor(){
}
}
class B extends A {
constructor() {
super();
}
}
上面代码中的super()代表的谁??
子类 B
的构造函数中的super()
,代表 B
调用父类 A
的构造函数执行。
注意⚠️: 虽然这里的 super()
代表了的 父类 A
的构造函数,但是返回的却是 子类 B
的实例,即 super()
内部的this 指的是 B, 因此 super()
在这里相当于 A.prototype.constructor.call(this)
。
用一个大栗子来证明我的论点:
class A {
constrctor(){
console.log(new.target.name)
}
}
class B extends A{
constructor(){
super()
}
}
new A() // A
new B() // B
在这段热气腾腾的代码中, new.target
指向当前正在执行的函数。
啰嗦一下:
new
是从构造函数生成的实例对象的命令。ES6 为 new
命令引入了一个 new.target
属性,该属性一般用在构造函数之中,返回new命令作用于的那个构造函数。
可以看到,在 super()
执行时,它指向的是子类 B
的构造函数,而不是父类 A
的构造函数。即 super()
内部的 this 指向的是 B
。
还有一点需要注意 ⚠️ :
作为函数时,super()只能用在子类的构造函数中,用在其他地方报错。
// 错误写法
class A {}
class B extends A {
m() {
super(); // 报错
}
}
总结一下:
当super 作为函数的时候需要注意以下三点:
- 子类的构造函数必须执行一次
super
函数。
// 再次重申,这是固定写法
class A {
constructor() {}
}
class B extends A {
constructor() {
super();// 这里表示 A.constructor()
}
}
- 子类的构造函数中的
super()
代表的是 子类调用父类的构造函数执行,这时候super()
中的this,即父类.constructor
中的this
,指向的是子类。
3.super()只能用在子类的构造函数之中,用在其他地方就会报错。
2.super作为对象时
super
作为对象时,在普通方法中,指向父类的原型对象,在静态方法中指向父类。
2.1 super作为对象在普通方法中应用
上代码:
class A {
p(){
return 2
}
}
class B extends A {
constrctor(){
super();
console.log(super.p());//2
}
}
let b = new B();
我们发现 在子类 B
中super.p()
执行结果为2
。我们猜测这里的supsuper.p === A.prototype.p
,验证一下发现结果是 true
:
class A {
p() {
return 2;
}
}
class B extends A {
constructor() {
super();
console.log(super.p===A.prototype.p); // true
}
}
let b = new B();
也就是说这个时候 super
在普通的方法中,指向的是 A.prototype
即子类中的super
指向父类的原型对象。
⚠️注意点 1. :由于子类中的super
指向父类的原型对象,所以定义在父类实例上的方法或属性,是无法通过super
调用的。
class A {
constructor() {
this.s = 3;
}
}
A.prototype.x = 2;
class B extends A {
constructor() {
super();
console.log(super.x) // 2 这里可以获取到父类原型上的x属性
}
get m(){
return super.s
}
}
let b = new B();
console.log(b.m)// undefined 不能获取到定义在父类实例上的s属性
通过上面的代码我们发现:
子类 B
可以通过super
获取到父类定义在原型上的属性,但是定义在父类 A
的实例上的属性,无法获取到。
注意点2⚠️:this指向
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();// 这里等同于 A.proptotype.print()
}
}
let b = new B();
b.m() // 2
上面代码中,super.print()
虽然调用的是A.prototype.print()
,但是 A.prototype.print()
内部的this指向子类B的实例,导致输出的是2,而不是1。也就是说,实际上执行的是 super.print.call(this)
。
注意点3⚠️:通过super
进行赋值操作
由于 this
指向子类实例,所以如果通过 super
对某个属性赋值,这时super
就是this
,赋值的属性会变成子类实例的属性。
class A {
constructor() {
this.x = 1;
}
}
class B extends A {
constructor() {
super();
this.x = 2;
super.x = 3;// 此时的 super 就是 b
console.log(super.x); // undefined 等用于是 A.prototype.x
console.log(this.x); // 3
}
}
let b = new B();
通过这两段代码我们发现了一个问题,当我通过 super
取值的时候取的是父类的原型上属性,但是当我通过 super
赋值的时候这时候 super
指向的是子类的实例。
总结一下:
通过上面的三个栗子得出,
super
作为对象在普通方法中应用时:
- 子类中的
super
指向父类的原型对象,所以定义在父类实例上的方法或属性,是无法通过super
调用的。 - 在子类普通方法中通过
super
调用父类的方法时,方法内部的 this 指向当前的子类实例。 - 通过 super 对某个属性赋值,这时super就是this,赋值的属性会变成子类实例的属性。
2.2 super作为对象在静态方法中应用
如果 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 指的是父类,Parent
super.myMethod(msg);
}
myMethod(msg) {
// 普通函数 此时 super 是指 Parent.prototype
super.myMethod(msg);
}
}
Child.myMethod(1); // static 1
var child = new Child();
child.myMethod(2); // instance 2
上面代码中,super在静态方法之中指向父类,在普通方法之中指向父类的原型对象。
注意点1 ⚠️
在子类的静态方法中通过 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();// A.print 中的this指向当前的子类
}
}
B.x = 3;
B.m() // 3
上面代码中,静态方法 B.m
里面,super.print
指向父类的静态方法。这个方法里面的 this
指向的是 B
,而不是 B
的实例。
总结一下:
在子类的静态方法中通过super
调用父类的方法时,方法内部的this
指向当前的子类,而不是子类的实例。
总之
super
作为函数,super()
代表的就是父类构造函数,里面的this
就是类的实例。super
作为对象,在普通的方法中super.
的语法指向的是父类的原型对象,在静态方法中使用super.
语法的话就去父类的静态方法中找就行了。至于this
指向问题,记住一点:如果在一个方法前,加上static
关键字,就表示该方法不会被实例继承,而是直接通过类来调用,所以静态方法中的this
只会指类而不是实例。
你真的了解[super ]关键字吗?的更多相关文章
- Java super关键字活用
在实际开发中我们要自定义组件,就需要继承自某个组件类,如果我们自定义的这个组件类也需要像被继承的这个组件类一样,拥有丰富的构造方法. 关键字super的作用就更加显得尤为重要了,你可以在堆砌自己自定义 ...
- 12.super关键字
①在java中使用super关键字来调用父类的成分
- this、super关键字
this关键字 this 关键字用来表示当前对象本身,或当前类的一个实例,通过 this 可以调用本对象的所有方法和属性. public class Demo{ public int x = 10; ...
- Java基础-super关键字与this关键字
用super调用父类构造方法 类如果没有显式声明构造方法,则自动生成无参数的默认构造方法. 1.先用一个无参数的父类构造方法验证一下, 执行子类构造方法会自动调用父类的构造方法.测试代码: class ...
- 使用 Object.create 创建对象,super 关键字,class 关键字
ECMAScript 5 中引入了一个新方法:Object.create().可以调用这个方法来创建一个新对象.新对象的原型就是调用 create 方法时传入的第一个参数: var a = {a: 1 ...
- 方法重写和方法重载;this关键字和super关键字
1:方法重写和方法重载的区别?方法重载能改变返回值类型吗? 方法重写: 在子类中,出现和父类中一模一样的方法声明的现象. 方法重载: 同一个类中,出现的方法名相同,参数列表不同的现象. 方法重载能改变 ...
- 继承进一步使用,以及super关键字
目标: 1)掌握子类对象实例化过程 2)掌握方法覆盖概念和实现. 3)掌握super关键字的作用. 一,子类对象实例化过程 子类对象在实例化之前,必须先调用父类中的构造方法,再调用子类中的构造方法. ...
- OC基础--self关键字&super关键字
PS:OC中的self关键字可以与C#中的this关键字区分记忆,虽然区别还是很大的. OC中的super关键字指的是父类指针 一.self关键字必须了解的知识: 1.使用场合:只能用在方法中(对象方 ...
- 面向对象编程(十)——继承之Super关键字及内存分析
Super关键字
随机推荐
- C# 给主程序签名及第三方dll强签名操作
1.给主程序添加签名 添加完成后会自动生成一个*.pfx文件. 2.给第三方程序添加强签名方法: 本文以WAPIWrapperCSharp.dll为例,使用vs Tools下的工具命令 ...
- 题目1102:最小面积子矩阵(暴力求解&最大连续子序列)
题目链接:http://ac.jobdu.com/problem.php?pid=1102 详解链接:https://github.com/zpfbuaa/JobduInCPlusPlus 参考代码: ...
- css修改select默认样式
先来看看效果图: css: <style media="screen"> .select_demo, .select_list { width: 400px; heig ...
- iOS property中的strong 、weak、copy 、assign 、retain 、unsafe_unretained 与autoreleasing区别和作用详解
iOS5中加入了新知识,就是ARC,其实我并不是很喜欢它,因为习惯了自己管理内存.但是学习还是很有必要的. 在iOS开发过程中,属性的定义往往与retain, assign, copy有关,我想大家都 ...
- MONGOOSE – 让NODE.JS高效操作MONGODB(转载)
Mongoose库简而言之就是在node环境中操作MongoDB数据库的一种便捷的封装,一种对象模型工具,类似ORM,Mongoose将数据库中的数据转换为JavaScript对象以供你在应用中使用. ...
- RestTemplate异常no suitable HttpMessageConverter found for request type [java.lang.Integer]
GET方式,参数必须放在URL后面,http://xxx/list?name={name}&age={age} package com.chelizi.xiruo.xframework.uti ...
- ELK篇---------elasticsearch集群安装配置
说明: 本次ELK的基础配置如下: 虚拟机:vmware 11 系统:centos7.2 两台 IP:172.16.1.15/16 一.下载es wget https://download.elas ...
- 字符串匹配 扩展KMP BM&Sunday
复杂度都是O(n) 扩展1:BM算法 KMP的匹配是从模式串的开头开始匹配的,而1977年,德克萨斯大学的Robert S. Boyer教授和J Strother Moore教授发明了一种新的字符串匹 ...
- CodeForces - 586D Phillip and Trains 搜索。vis 剪枝。
http://codeforces.com/problemset/problem/586/D 题意:有一个3*n(n<100)的隧道.一个人在最左边,要走到最右边,每次他先向右移动一格,再上下移 ...
- MySQL ·InnoDB 文件系统之文件物理结构
从上层的角度来看,InnoDB层的文件,除了redo日志外,基本上具有相当统一的结构,都是固定block大小,普遍使用的btree结构来管理数据.只是针对不同的block的应用场景会分配不同的页类型. ...