Quelle est la méthode standard pour appeler des méthodes statiques? Je peux penser à utiliser constructor
ou à utiliser le nom de la classe elle-même. Je n'aime pas ce dernier car il ne me semble pas nécessaire. Le premier est-il le moyen recommandé ou y at-il autre chose?
Voici un exemple (artificiel):
class SomeObject {
constructor(n){
this.n = n;
}
static print(n){
console.log(n);
}
printN(){
this.constructor.print(this.n);
}
}
Les deux méthodes sont viables, mais elles font des choses différentes en matière d'héritage avec une méthode statique surchargée. Choisissez celui dont vous attendez le comportement:
_class Super {
static whoami() {
return "Super";
}
lognameA() {
console.log(Super.whoami());
}
lognameB() {
console.log(this.constructor.whoami());
}
}
class Sub extends Super {
static whoami() {
return "Sub";
}
}
new Sub().lognameA(); // Super
new Sub().lognameB(); // Sub
_
Faire référence à la propriété statique via la classe sera réellement statique et donnera constamment la même valeur. Utiliser _this.constructor
_ à la place utilisera la répartition dynamique et fera référence à la classe de l'instance actuelle, où la propriété statique pourrait avoir la valeur héritée, mais pourrait également être remplacé.
Cela correspond au comportement de Python, dans lequel vous pouvez choisir de faire référence à des propriétés statiques via le nom de la classe ou l'instance self
.
Si vous vous attendez à ce que les propriétés statiques ne soient pas remplacées (et faites toujours référence à celle de la classe actuelle), comme en Java , utilisez la référence explicite.
Je suis tombé sur ce fil en cherchant une réponse à un cas similaire. En gros, toutes les réponses sont trouvées, mais il est toujours difficile d’en extraire l’essentiel.
Supposons une classe Foo probablement dérivée d'une autre classe avec probablement plus de classes dérivées de celle-ci.
Puis accéder
this.method()
this.property
Foo.method()
Foo.property
this.constructor.method()
this.constructor.property
this.method()
this.property
Foo.method()
Foo.property
Foo.prototype.method.call( this )
Object.getOwnPropertyDescriptor( Foo.prototype,"property" ).get.call(this);
N'oubliez pas que l'utilisation de
this
ne fonctionne pas de cette manière lorsque vous utilisez des fonctions de flèche ou invoquez des méthodes/accesseurs liés explicitement à une valeur personnalisée.
this
fait référence à l'instance actuelle.super
fait essentiellement référence à la même instance, mais des méthodes d'adressage et des accesseurs écrits dans le contexte d'une classe courante sont en train de s'étendre (en utilisant le prototype du prototype de Foo).this.constructor
.this
est disponible pour se référer directement à la définition de la classe actuelle.super
ne fait pas non plus référence à une instance, mais à des méthodes statiques et à des getters écrits dans le contexte d'une classe de classe en cours d'extension.Essayez ce code:
class A {
constructor( input ) {
this.loose = this.constructor.getResult( input );
this.tight = A.getResult( input );
console.log( this.scaledProperty, Object.getOwnPropertyDescriptor( A.prototype, "scaledProperty" ).get.call( this ) );
}
get scaledProperty() {
return parseInt( this.loose ) * 100;
}
static getResult( input ) {
return input * this.scale;
}
static get scale() {
return 2;
}
}
class B extends A {
constructor( input ) {
super( input );
this.tight = B.getResult( input ) + " (of B)";
}
get scaledProperty() {
return parseInt( this.loose ) * 10000;
}
static get scale() {
return 4;
}
}
class C extends B {
constructor( input ) {
super( input );
}
static get scale() {
return 5;
}
}
class D extends C {
constructor( input ) {
super( input );
}
static getResult( input ) {
return super.getResult( input ) + " (overridden)";
}
static get scale() {
return 10;
}
}
let instanceA = new A( 4 );
console.log( "A.loose", instanceA.loose );
console.log( "A.tight", instanceA.tight );
let instanceB = new B( 4 );
console.log( "B.loose", instanceB.loose );
console.log( "B.tight", instanceB.tight );
let instanceC = new C( 4 );
console.log( "C.loose", instanceC.loose );
console.log( "C.tight", instanceC.tight );
let instanceD = new D( 4 );
console.log( "D.loose", instanceD.loose );
console.log( "D.tight", instanceD.tight );
Si vous envisagez de faire n'importe quel type d'héritage, je vous recommanderais donc this.constructor
. Cet exemple simple devrait illustrer pourquoi:
class ConstructorSuper {
constructor(n){
this.n = n;
}
static print(n){
console.log(this.name, n);
}
callPrint(){
this.constructor.print(this.n);
}
}
class ConstructorSub extends ConstructorSuper {
constructor(n){
this.n = n;
}
}
let test1 = new ConstructorSuper("Hello ConstructorSuper!");
console.log(test1.callPrint());
let test2 = new ConstructorSub("Hello ConstructorSub!");
console.log(test2.callPrint());
test1.callPrint()
enregistrera ConstructorSuper Hello ConstructorSuper!
sur la consoletest2.callPrint()
enregistrera ConstructorSub Hello ConstructorSub!
sur la consoleLa classe nommée ne traitera pas bien l'héritage à moins que vous ne redéfinissiez explicitement chaque fonction qui fait référence à la classe nommée. Voici un exemple:
class NamedSuper {
constructor(n){
this.n = n;
}
static print(n){
console.log(NamedSuper.name, n);
}
callPrint(){
NamedSuper.print(this.n);
}
}
class NamedSub extends NamedSuper {
constructor(n){
this.n = n;
}
}
let test3 = new NamedSuper("Hello NamedSuper!");
console.log(test3.callPrint());
let test4 = new NamedSub("Hello NamedSub!");
console.log(test4.callPrint());
test3.callPrint()
enregistrera NamedSuper Hello NamedSuper!
sur la consoletest4.callPrint()
enregistrera NamedSuper Hello NamedSub!
sur la consoleVoir tout ce qui précède dans Babel REPL .
Vous pouvez voir que test4
pense toujours que c'est dans la super classe; dans cet exemple, cela peut ne pas sembler une grosse affaire, mais si vous essayez de référencer des fonctions membres qui ont été remplacées ou de nouvelles variables membres, vous aurez des problèmes.