簡體   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