[英]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.