八. super
super关键字在js中一般是作为函数使用,但是也可以作为对象去调用父类的方法- 第一种情况:es6规定,子类的构造函数必须执行一次super函数
class Father{
constructor(){
console.log(new.target.name);
}
}
class Child extends Father{
constructor(){
super()
}
}
new Father()
new Child()
- 第二种情况:
子类中使用super.xxx()就是把super作为一个对象使用 注意:不能super.xx来获取属性!子类使用super.xxx()就是子类去调用该方法,this指向子类
class Father{
p(){
console.log(this);
return 'Father'
}
}
class Child extends Father{
constructor() {
super()
console.log(super.p())
}
}
new Child();
super.xx不能获取父类属性,是因为super指向的是父类的原型对象,所以定义在父类实例上的方法或者属性是无法通过super来调用的
class Father{
name = 'Father';
func = function(){return '类中通过this.xxx=function(){}得到的是实例方法'}
constructor() {
this.age = 1;
}
protoFunc(){
return '父类原型上的方法'
}
}
class Child extends Father{
getAge(){
return super.age
}
getName(){
return super.name
}
getFunc(){
return super.func()
}
getProtoFunc(){
return super.protoFunc()
}
}
let b = new Child()
console.log(Father.prototype)
console.log(b.age)
console.log(b.name)
console.log(b.getAge())
console.log(b.getName())
console.log(b.getProtoFunc())
Father.prototype.age = 'prototype方式赋值'
console.log(b.getAge())
super.xxx=xxx赋值实际上是对子类的属性进行赋值
class A {
constructor() {
this.x = 1;
}
}
class B extends A {
constructor() {
super();
this.x = 2;
super.x = 3;
console.log(super.x);
console.log(this.x);
}
}
let b = new B();
- 在
static静态方法中使用super,super此时指向的是父类而不是父类的原型对象
class Father{
static getName(name){
return 'static:'+name;
}
getName(name){
return 'Father内部普通方法:'+name;
}
}
class Child extends Father{
static getName(name){
return '子类static:'+super.getName(name);
}
getName(name){
return '子类:'+super.getName(name);
}
}
console.log(Child.getName('1'))
console.log(new Child().getName('2'))
console.log(Father.prototype)
console.log(new Child().getName('3'))
由于对象总是继承其他对象的,所以在任意对象中都可以使用super关键字
let obj = {
toString(){
console.log(super.toString())
}
}
let father = {
toString(){
return 'father'
}
}
obj.__proto__ = father;
console.log(obj)
obj.toString()
类具有两条继承链!
- 类作为构造函数的语法糖,同时具有prototype和__proto__两条继承链
- 第一条:
子类的__proto__属性 表示构造函数的继承,总是指向父类 - 第二条:
子类的prototype属性的__proto__属性,表示方法的继承,总是指向父类的prototype属性
class Father{}
class Child extends Father{}
console.log(Child.__proto__ === Father)
console.log(Child.prototype.__proto__ === Father.prototype)
console.log(new Child().__proto__.__proto__ === new Father().__proto__)
class A{
getName(){
return 'a'
}
}
class B{}
Object.setPrototypeOf(B.prototype, A.prototype)
Object.setPrototypeOf(B, A)
console.log(A.prototype)
console.log(B.prototype)
console.log(new A().__proto__)
console.log(new B().__proto__)
console.log(new B().getName())
Object.setPrototypeOf方法的原理
Object.setPrototypeOf = function(a, b){
a.__proto__ = b;
return a;
}
类可以继承有prototype属性的对象
- 第一种情况:
子类继承Object对象(也就是原生构造对象,可以new的,有构造器函数的对象)/函数/类
// 1. 继承没有构造器的对象
/* let obj = {name:
class Child extends obj{
getName(){
return this.name;
}
}
console.log(new Child().getName())
// Class extends value #<Object> is not a constructor or null */
// 2. 继承Object对象
/* class Child extends Object{
getName(){
return this.toString();
}
}
console.log(new Child().getName()) //[object Object]
*/
// 3. 继承自定义构造器的对象(事实证明自定义的构造器对象失败,不了解构造器底层实现)
// Class extends value #<constructor> is not a constructor or null
/* let obj = {
constructor(){
this.name =
}
}
class Child extends obj{
getName(){
return this.toString();
}
}
console.log(new Child().getName()) */
// 4. 子类继承函数
function A(){}
class Child extends A{
getName(){
return this.toString();
}
}
console.log(new Child().getName()) //[object Object]
// 4.1 给函数原型对象添加属性
A.prototype.name =
console.log(new Child().name) // yiye
class Child{}
console.log(Child.__proto__ === Function.prototype)
console.log(Function.prototype.__proto__ === Object.prototype)
console.log(Child.prototype.__proto__ === Object.prototype)
本文参考阮一峰ES6教程