调用静态方法的标准方法是什么?我可以考虑使用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的行为相符,在Python中,您可以选择通过类名或实例来引用静态属性self
。
如果您希望不重写静态属性(并且始终引用当前类之一),例如在Java中,请使用显式引用。
我偶然发现了这个线程以寻找类似情况的答案。基本上可以找到所有答案,但是仍然很难从中提取要点。
访问种类
假设一个类Foo可能派生自某些其他类,并且可能派生出更多的类。
然后访问
- 来自Foo的静态方法/获取器
- 一些可能覆盖的静态方法/获取器:
this.method()
this.property
- 一些可能覆盖的实例方法/获取器:
- 设计不可能
- 自己的非重写静态方法/获取器:
Foo.method()
Foo.property
- 自己的非重写实例方法/获取器:
- 设计不可能
- 一些可能覆盖的静态方法/获取器:
- 从实例方法/ Foo的getter
- 一些可能覆盖的静态方法/获取器:
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
当使用箭头功能或调用显式绑定到自定义值的方法/获取器时,使用不能以这种方式工作。
背景
- 在实例的方法或getter上下文中
this
是指当前实例。super
基本上指的是同一实例,但是某种寻址方法和在某些类的上下文中获取的方法正在扩展(通过使用Foo原型的原型)。- 实例类的定义可用于创建实例
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!
到控制台
从中可以看出,test4
仍然认为它属于超类。在此示例中,这似乎没什么大不了的,但是如果您尝试引用已被重写的成员函数或新的成员变量,则会发现自己遇到了麻烦。
本文地址:http://javascript.askforanswer.com/congchangguies6leifangfadiaoyongjingtaifangfa.html
文章标签:class , ecmascript-6 , es6-class , javascript , static
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!
文章标签:class , ecmascript-6 , es6-class , javascript , static
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!
评论已关闭!