繁体   English   中英

Javascript ES6 中的 Static 构造函数

[英]Static Constructor in Javascript ES6

在 ES6 中,我可以创建 static 方法,如下所示。 但我需要定义一个 static 构造函数但没有成功。 我需要在加载 class 时只运行一次的东西。 我有没有办法实现这样的事情?

class Commander{

    static onData(){
         console.log("blabla");
    }
}

在类主体中包含类设置代码似乎更简洁,因此“类表达式”是自包含的。 ES6 在类体中接受语法static constructor() {/* do stuff */}但从不运行它。 也许是为了未来的语言扩展? 无论如何,这是实现预期结果的一种方法。 诀窍是使用立即执行的函数表达式初始化静态属性,该函数表达式会执行您的类设置:

 class MyClass { static _staticConstructorDummyResult = (function() { console.log('static constructor called') // once! })() constructor () { console.log('instance constructor called') } } let obj = new MyClass(), obj2 = new MyClass()

在“静态构造函数”中,您可以使用MyClass.prop = value向类对象添加属性,或者如果您希望将MyClass称为this ,请将函数表达式更改为箭头函数表达式

您可以使用Object.defineProperty()使_staticConstructorDummyResult不可枚举,或者如果您不介意需要 Chrome(它目前不适用于 Firefox),您可以在名称前面添加一个#以使其成为私有财产。

我需要在类加载时只运行一次的东西。

如果您只是将它们用作一组方法,则不应该使用它们。 改用一个对象。 但是,仍然可以运行此类代码。 只需将其放在类定义之前或之后即可。

console.log('before class is created')

class Foo {}

console.log('after class was created');

如果您坚持使用静态构造函数:定义一个静态方法并在类定义之后调用它。

class Foo {
  static staticConstructor() {
    console.log('Foo has been constructed statically!');
  }
}

Foo.staticConstructor()

当然,这并不是真正必要的。 除了 mabye 清楚地表达静态构造函数的概念。 然而,这闻起来像 Java。

Felix 提出了一个很好的解决方案,即在类定义之前或之后放置代码。

例如:要预先计算一些静态成员吗​​? 只需在类定义后分配计算结果即可!

class Foo {}

Foo.preCalculated = calculate();

function calculate() {
  console.log('Do some hard work here');
  return 'PRECALCULATED';
}

在 ES2022 中,我们现在有static 初始化块,如下所示:

class Commander {
  static {
    // Arbitrary code goes in here and is run immediately
    // You can use `this` to reference the class (instead of having to use its name):
    this.foo = 'foo'; // sets a static property
  }
}

使用新的类属性初始值设定项,您可能根本不需要函数(对于简单表达式)。

初始化器是类定义上下文中的=表达式,它的作用就像是构造函数中的表达式,所以this是定义的(因为初始化器在构造函数链之后)。

class Toto {
    foo = 'bar'
    bar = this.foo
    baz = this.method()
    method(){ return 'baz' }
}
console.log( new Toto )
//> Toto {foo: "bar", bar: "bar", baz: "baz"}

静态初始化的工作方式相同,但是this是实际的构造函数(类),它是一个静态方法定义的方式相同。

class Toto {
    static foo = 'bar'
    static bar = this.foo
    static baz = this.method()
    static method(){ return 'baz' }
}
console.dir( Toto )
//> class Toto {name: "Toto", foo: "bar", bar: "bar", baz: "baz", method: ƒ method()}

使用父类声明在初始化期间要调用的静态方法非常方便:

class Base extends HTMLElement {
    static define( tag )
    {
        return customElements.define( this, tag )
    }
}

//then

class MyElement extends Base {
    constructor(){ ... }
    static defined = this.define( 'my-el' )
}

您还可以使用静态 getter/setter:

/** utils */
const CSS = css=> { let s = new CSSStyleSheet; s.replaceSync(css); return s }

class Base extends HTMLElement {
    /**
     * node.shadowRoot getter to access shadowRoot with direct creation if not existing yet.
     * @exemple class extends HTMLElement { constructor(){ super(); this.shadowRoot.innerHTML = '...' } }
     * @exemple class extends HTMLElement { html = this.shadowRoot.innerHTML = '...' }
     */
    get shadowRoot()
    {
        return super.shadowRoot || this.attachShadow({mode:'open'})
    }
    adoptedCSS = this.shadowRoot.adoptedStyleSheets = [ this.constructor.css ]
    static set tag( v )
    {
        return customElements.define( this, v )
    }
}

//then

class MyElement extends Base {
    title = 'Default title'
    html = this.shadowRoot.innerHTML = `
        <div class=super>
            <h1>${this.title}</h1>
        </div>
    `
    $title = this.shadowRoot.querySelector('div > h1')

    static css = CSS`
        :host       { outline: 1px solid blue }
        div         { outline: 1px solid green }
    `
    static defined = this.tag = 'my-el'

    // static tag = 'my-el' << this won't work because initializers use  
    // Object.defineProperty and not a direct set, so the setter  
    // will be overwritten!
}

// Note: no need of any framework here

支持:

资料来源:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM