什么是调用静态方法的标准呢? 我能想到使用constructor
或使用类本身的名字,我不喜欢后者,因为它不觉得有必要。 是前者推荐的方式,或者是有别的原因呢?
这里的(人为)例如:
class SomeObject {
constructor(n){
this.n = n;
}
static print(n){
console.log(n);
}
printN(){
this.constructor.print(this.n);
}
}
两种方式都是可行的,但他们做不同的事情,当谈到有一个重写的静态方法来继承。 选择它的行为您所期望的一个:
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
通过类指的是静态属性将是真正的静态不断给予相同的值。 使用this.constructor
反而会使用动态调度和引用类的当前实例,其中静态属性可能具有遗传价值的,但也可以覆盖。
这符合Python的,在这里你可以选择参考静态属性或者通过类名或实例的行为self
。
如果你希望静态属性不被覆盖(并总是指当前类的一个), 像在Java中 ,使用明确的参考。
我绊了这个线程寻找答案,类似的案例。 基本上所有的答案被发现,但它仍然很难从中提取的要领。
访问的种类
假设一个类Foo可能从其他类(ES)从它派生的可能更多的类派生的。
然后访问
- 从富的静态方法/吸气剂
- 一些可能覆盖静态方法/吸气:
-
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);
请记住,使用this
使用箭头功能或调用方法时,不以这种方式工作/干将明确绑定到自定义值。
背景
- 当一个实例的方法或吸气的情况下
-
this
指的是当前实例。 -
super
基本上是指同一个实例,但有些寻址(通过使用Foo原型的原型)写在一些类当前正在扩大的背景下方法和getter。 - 在创建它使用实例的类定义是每间可用
this.constructor
。
- 当在静态方法或吸气剂的上下文中没有“当前实例”意向等
-
this
可用来指代当前直接类的定义。 -
super
是不是指一些实例要么,而是写在某类当前的背景下静态方法和getter正在扩大。
结论
试试这个代码:
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 );
如果你正在做的任何一种传承规划,那么我会建议this.constructor
。 这个简单的例子应该说明原因:
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()
将记录ConstructorSuper Hello ConstructorSuper!
控制台 -
test2.callPrint()
将记录ConstructorSub Hello ConstructorSub!
控制台
命名类不会继承处理很好,除非你明确地重新定义每个函数说对已命名的类的引用。 下面是一个例子:
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()
将记录NamedSuper Hello NamedSuper!
控制台 -
test4.callPrint()
将记录NamedSuper Hello NamedSub!
控制台
见通天REPL上述所有正在运行 。
你可以从这个是看test4
仍然认为它在超类; 在这个例子中看起来可能不是一个巨大的交易,但如果你正在尝试引用已被覆盖的成员函数或新的成员变量,你会发现自己陷入困境。