从调用定期ES6类方法的静态方法从调用定期ES6类方法的静态方法(Call static metho

2019-05-10 11:38发布

什么是调用静态方法的标准呢? 我能想到使用constructor或使用类本身的名字,我不喜欢后者,因为它不觉得有必要。 是前者推荐的方式,或者是有别的原因呢?

这里的(人为)例如:

class SomeObject {
  constructor(n){
    this.n = n;
  }

  static print(n){
    console.log(n);
  }

  printN(){
    this.constructor.print(this.n);
  }
}

Answer 1:

两种方式都是可行的,但他们做不同的事情,当谈到有一个重写的静态方法来继承。 选择它的行为您所期望的一个:

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中 ,使用明确的参考。



Answer 2:

我绊了这个线程寻找答案,类似的案例。 基本上所有的答案被发现,但它仍然很难从中提取的要领。

访问的种类

假设一个类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 ); 



Answer 3:

如果你正在做的任何一种传承规划,那么我会建议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仍然认为它在超类; 在这个例子中看起来可能不是一个巨大的交易,但如果你正在尝试引用已被覆盖的成员函数或新的成员变量,你会发现自己陷入困境。



文章来源: Call static methods from regular ES6 class methods