你真的了解[super ]关键字吗?
栏目: JavaScript · 发布时间: 6年前
内容简介:此篇文章是看了阮老师的es6教程,看到
此篇文章是看了阮老师的es6教程,看到 super
关键字的时候觉得有必要总结梳理一下,原文还是参考ECMAScript 6入门。
正文
super
这个关键字,既可以当作函数使用,也可以当作对象使用。
1.当作函数使用
super
作为函数调用时,代表父类的构造函数。 ES6
要求 ,子类的构造函数必须执行一次 super
函数。
即作为 函数
使用时下面的代码时 固定使用套路
:
class A { constrctor(){ } } class B extends A { constructor() { super(); } } 复制代码
上面代码中的super()代表的谁??
子类 B
的构造函数中的 super()
,代表 B
调用父类 A
的构造函数执行。
注意:warning:: 虽然这里的 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
。
还有一点需要注意:warning: :
作为函数时,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
指向父类的原型对象。
:warning: 注意点 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:warning:: 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:warning::
通过 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 :warning:
在子类的静态方法中通过 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 ]关键字吗?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 从对象头出发了解Synchronized关键字
- 番外篇2-基本规范、注释、static关键字、import关键字
- 说说iOS中的常用的关键字static ,class(仅限Swift关键字)
- Golang 关键字
- 2019 关键字
- golang关键字
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Mastering Regular Expressions, Second Edition
Jeffrey E F Friedl / O'Reilly Media / 2002-07-15 / USD 39.95
Regular expressions are an extremely powerful tool for manipulating text and data. They have spread like wildfire in recent years, now offered as standard features in Perl, Java, VB.NET and C# (and an......一起来看看 《Mastering Regular Expressions, Second Edition》 这本书的介绍吧!