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

时间:2015-09-09 16:48:03

标签: 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;
    }
}

我们的想法是,有Parent个类扩展了Child个类ChilddoImportantStuff()类的初始化大致相同,但每个类都有自己的Child实现,其返回值指示是否应该实例化特定的this

到目前为止,这已经在我尝试过的每个转换器中都有效,因为Parent.init()函数中的Child引用了<div class="bg-image"> <!-- Featured Content absolute --> </div> <div class="content-wrap"> <!-- More Content --> </div> 类的构造函数。但是,我还没有找到任何文档说明引用由子类重写的静态方法的方法,所以问题是,我可以依赖于此吗?或者,还有其他方法可以做到吗?

2 个答案:

答案 0 :(得分:9)

  

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

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

Child1.doImportantStuff();

...除非doImportantStuff是箭头函数(它不是)或绑定函数(它不是),否则在调用期间,this设置为Child1 }。完全像:

var obj = {
   foo: function() {
        console.log(this === obj);
   }
};
obj.foo();   // "true"

所以是的,你可以依靠它。 (我理解你为什么这么问,除非你完成它,否则似乎有点奇怪。)

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

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

答案 1 :(得分:6)

如果您不想致电

Child1.doImportantStuff();

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

this.constructor.doImportantStuff();

这也适用于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'