从父级调用重写的静态方法

Sch*_*aus 14 javascript ecmascript-6

首先,设置阶段的一些代码:

var instances = [];

class Parent {
    static doImportantStuff() {
        console.log( 'Parent doing important stuff' );
        return false;
    }

    static init() {
        if ( this.doImportantStuff() )
            instances.push( new this() );
    }
}

class Child1 extends Parent {
    static doImportantStuff() {
        console.log( 'Child 1 doing important stuff' );
        if (someCondition) return true;
        return false;
    }
}

class Child2 extends Parent {
    static doImportantStuff() {
        console.log( 'Child 2 doing important stuff' );
        if (someOtherCondition) return true;
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

这个想法是有一个类Parent可以Child扩展几个类.Child类的初始化大致相同,但每个都有自己的实现doImportantStuff(),其返回值指示是否Child应该实例化该特定.

到目前为止,这已经在我尝试过的每个转换器中都有效,因为thisParent.init()函数中引用了Child类的构造函数.但是,我没有找到任何文档说明一种方式或另一种方式来引用由子类重写的静态方法,所以问题是,我可以依赖于此吗?或者,还有其他方法可以做到这一点吗?

T.J*_*der 13

但是,我没有找到任何文档说明一种方式或另一种方式来引用由子类重写的静态方法,所以问题是,我可以依赖于此吗?

它是标准的函数call-via-object-property机制.当你这样做时:

Child1.doImportantStuff();
Run Code Online (Sandbox Code Playgroud)

...除非doImportantStuff是箭头功能(它不是)或绑定功能(它不是),那么在通话期间,this设置为Child1.完全像:

var obj = {
   foo: function() {
        console.log(this === obj);
   }
};
obj.foo();   // "true"
Run Code Online (Sandbox Code Playgroud)

所以是的,你可以依靠它.(而且我理解你为什么这么问,除非你通过它,否则看起来有点奇怪.)

当然,它不会在非static函数的代码中起作用,因为this它将引用实例,而不是构造函数.如果你需要它,你可以使用,this.constructor.doImportantStuff除非有人搞砸了constructor财产.(人们总是习惯把它弄乱;用新的语法自动化它,希望这种情况会少发生,尽管你很少需要它......)


对于这些类型的问题,记住新的类语法几乎只是我们所做的旧冗长方式的语法糖(如果我们真的很彻底).这是非常好的糖,但这几乎就是它的全部(这是一件好事).static方法被设置为构造函数的属性,非static方法被设置为构造函数属性上的对象的prototype属性.(我认为,正如Bergi所指出的那样,它的唯一非糖方面是新语法允许我们扩展内置类似Array以前无法做到的内容.使这可能的一部分与设置的方式和this时间有关[你不能在之前访问它super()调用你的子类构造函数],这与new.targetBergi这里讨论.在ES7中,它可能会超出糖的隐私范围.)


Kil*_*ner 9

如果你不想打电话

Child1.doImportantStuff();
Run Code Online (Sandbox Code Playgroud)

in Parent,而是动态调用重写的静态方法,你可以这样做:

this.constructor.doImportantStuff();
Run Code Online (Sandbox Code Playgroud)

这也适用于setter和父类的构造函数:

class Parent {
  static get foo() {
        // Throw an error to indicate that this is an abstract method.
        throw new TypeError('This method should be overridden by inheriting classes.');
  }

  constructor() {
        console.log(this.constructor.foo);
  }

  logFoo() {
        console.log(this.constructor.foo);
  }
}

class Child extends Parent {
  static get foo() {
        return 'yay';
  }
}

const child = new Child(); // Prints 'yay'
child.logFoo(); // Prints 'yay'
Run Code Online (Sandbox Code Playgroud)