Разбор ключевого слова super в JavaScript

JavaScript

предисловие

пишуReactв классеclassОбъявленные компоненты, часто можно увидеть, что инициализация данных в компонентах React часто помещается вconstructorВнутри функции конструктора, в то время как подкласс наследуетReact.ComponentЕсли вы хотите получить данные из родительского компонента

то вы должны позвонитьsuper(props), а также требуетconstructorФункция-конструктор получаетpropsпараметр, иначе значение, переданное внешним компонентом, не может быть получено в текущем компоненте, как показано ниже

import React, { Component } from 'react'
import ReactDom from 'react-dom'


class Button extends Component {
 constructor(props) {
      super(props)
      
  }
  render() {
    const { content } = this.props;
    return (
      <div>
           <button>{ content }</button>
      </div>
    )
  }
}

const container = document.getElementById('root');

ReactDOM.render(<Button content="按钮" />, container);

В React вы часто будете видеть приведенный выше код, если компоненту нужно определить свой собственный конструктор, то его нужно вызыватьsuper(props), то есть унаследовалReact.ComponentКонструктор

А зачем звонитьsuper(props)метод, потому что Es6 сначала создает this экземпляра родительского класса, а затем использует конструктор подкласса для изменения этого

если нетconstructorфункция-конструктор, вызовsuper(), а параметрыprops, он сообщит об ошибке

После создания экземпляра компонента все функции-члены этого компонента не могут быть переданыthis.propsДоступ к переданному от родительского компонентаpropsстоимость

Давайте узнаем больше оsuperэто ключевое слово

Это не просто ключевое слово, его можно использовать как функции и объекты.

super вызывается как функция

когдаsuperКогда он вызывается как функция, он ссылается на конструктор родительского класса, а конструктор подкласса должен один раз выполнить суперфункцию.

То есть в подклассе, наследующем родительский класс, еслиsuperКак вызов функции его можно записать только в конструкторе подкласса,superПредставляет конструктор родительского класса

class A {          // class关键字声明了一个类A
  constructor() {
  }
}

class B extends A { // class关键字声明了B继承自A类
  constructor() {   // constructor构造器函数
    super();        // 调用super()
  }
}

new A() // A
new B() // B

В приведенном выше коде в конструкторе подкласса Bsuper(), который представляет вызов конструктора родительского класса. Это обязательно, иначе движок JavaScript сообщит об ошибке.

Уведомление

superХотя он представляет конструктор родительского класса A, он возвращает экземпляр подкласса B, то есть this внутри super ссылается на экземпляр B

здесьsuperэквивалент класса АconstructorКонструктор, выполнит Aconstructor, но в это времяthisуказывает на B, поэтому выведите B

Другое понимание: в реализацииsuperВ это время A передает метод конструктора B. В это время B имеет функцию A, но выполняет содержимое B, то есть es5.A.prototype.constructor.call(this)

И как вызов функции: он должен вызываться только в функции-конструкторе подкласса (конструкторе), если он размещен в другом месте, он сообщит об ошибке следующим образом:

class A {}

class B extends A {
  fun() {
    super(); // 报错,super()不能放置在函数内调用
  }
}

В приведенном выше кодеsuper()используется в классе Bfunметод, это вызовет синтаксическую ошибку

использовать super как объект

superПри использовании в качестве объекта он делится наиспользуется в обычных методахИ виспользуется в статических методах

  • Используйте обычный метод:superуказать на прототип родительского класса, т.е.A.prototype, вы можете получить доступ к методам и свойствам прототипа, то есть объекта-прототипа, который указывает на его родительский класс.
class Animal {     // class关键字声明了一个Animal类
    constructor() {
    }
    parent(){  // 类Animal的一个方法
        console.log('我是父类Animal的普通方法... ...');
    }
}

class Dog extends Animal {   // class关键字定义了Dog继承自Animal类
    constructor() {
        super()
    }
   watchHome(){            // 子类watchHome为Dog的方法
       super.parent() // 我是父类的普通方法
       // 等价于Animal.prototype.parent() // // 我是父类的普通方法
   }
}
const dog = new Dog()
dog.watchHome()

В приведенном выше коде подклассDogсредиsuper.parent(), то естьsuperПри использовании в качестве объекта в это времяsuperОбычными методами, указывая наA.prototype, такsuper.parent()эквивалентноAnimal.prototype.parent()

Уведомление

из-заsuperУказывает на объект-прототип родительского класса, поэтому методы или свойства, определенные в экземпляре родительского класса, не могут быть переданыsuperназывается

class Animal {
    constructor() {
        this.name = '父类上的实例上的属性'
    }
}

class Dog extends Animal {
   watchHome(){
       return super.name
   }
}
const dog = new Dog()
console.log(dog.watchHome()); // undefined,定义在父类实例上的属性, 无法通过super调用

в приведенном выше кодеnameэто родительский классAnimalсвойства экземпляра,super.nameне могу это процитировать

Но если свойство определено в объекте-прототипе родительского класса,superможно получить следующим образом

class Animal {

}

Animal.prototype.name = 'super实例上的属性'

class Dog extends Animal {
    watchHome() {
        return super.name
    }
}

const dog = new Dog()
console.log(dog.watchHome()); // super实例上的属性,可以拿到父类中原型下的name属性,定义在原型下的属性和方法都是公有的

пока вES6указывается в обычном методе подкласса с помощьюsuperПри вызове метода родительского класса метод внутриthisУказывает на экземпляр текущего подкласса.

class A {
  constructor() {
    this.name = "itclanCoder";   // 定义在A类的私有属性
  }
  print() {   // 定义在A类的print私有方法
    console.log(this.name);
  }
}

class B extends A {  // 类B继承自类A
  constructor() {
    super();         // 调用父类的super
    this.name = "随笔川迹";     // 子类B的私有属性
  }
  m() {
    super.print();
  }
}

let b = new B();
b.m() // 随笔川迹

super.print()Хотя звонитA.prototype.print(),ноA.prototype.print()Внутреннийthisуказывает на экземпляр подкласса B В результате выводится «Эссе» вместо «itclanCoder». То есть то, что на самом деле выполняется,super.print.call(this)

Эта функция полезна и может использоваться для переопределения (переопределения) частных свойств родительского класса.

из-заthisВ этот момент он указывает на экземпляр подкласса, поэтому, если вы передадитеsuperПрисвойте значение свойству, затем это супер, и присвоенное свойство станет свойством экземпляра подкласса.

class A {
  constructor() {
    this.name = "itclanCoder";
  }
}

class B extends A {
  constructor() {
    super();
    this.name = "itclan";     // 子类B的私有属性
    super.name = "川川";
    console.log(super.name);  // undefined,super是父类,而name是父类的私有属性,无法直接访问
    console.log(this.name);   // 川川
  }
}

let b = new B();

В приведенном выше примере кодаsuper.nameПрисвойте значение «Чуаньчуань», что эквивалентноthis.nameназначить как川川. и при чтенииsuper.name, он читаетA.prototype.name, так что возвращайсяundefined

  • Если используется в статическом методе

еслиsuperКак объект, используемый в статических методах, тоsuperбудет указывать на родительский класс вместо родительского объекта-прототипа

class Parent {
    static myMethod(msg) {  // 父类的方法之前加静态static关键字
        console.log('static1', msg);
    }

    myMethod(msg) {            // 父类的私有普通方法
        console.log('instance2', msg);
    }
}

class Child extends Parent {  // 类child继承自篇Parent
    static myMethod(msg) {    // 子类的私有myMethod方法前声明static
        super.myMethod(msg); // super在静态方法中指向父类, 而不是父类的原型
    }

    myMethod(msg) {
        super.myMethod(msg); // super在普通方法中指向父类的原型
    }
}

Child.myMethod(1); // static1 1

var child = new Child();
child.myMethod(2); // instance2 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 so указывает на экземпляр B, поэтомуsuper.valueOf()возвращает экземпляр B

instanceof: рольA instanceof B, является ли A экземпляром B, и если да,true, если нет тоfalse

Суммировать

оsuperИспользование ключевых слов действительно сложно.Основная функция в том, что метод родительского класса может быть вызван в подклассе.При вызове обычного метода родительского класса в подклассе его можно только определить и поместить в функцию-конструктор , в противном случае будет сообщено об ошибке. , вы не можете напрямую ссылаться на частные свойства родительского класса, но вы можете применить свойства и методы прототипа в родительском классе

superКлючевое слово может использоваться для переопределения и переопределения свойств в родительском типе, что также является одной из его функций.Иногда во время интервью, пока вы спрашиваете о наследовании классов, если вы углубитесь, вы спроситеsuperключевые слова

При объектно-ориентированной разработке этоsuperтакже очень важно

Связанные справочные документы

Для получения большего количества контента вы можете обратить внимание на общедоступную учетную запись WeChat itclanCoder, полезную учетную запись, которая только доставляет и делится с вами вдохновением и мудростью.