在 ES6 中,我可以创建如下所示的静态方法。但我需要定义一个静态构造函数但没有成功。我需要在类加载时仅运行一次的东西。我有什么办法可以实现这样的事情吗?
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
,请将函数表达式更改为 箭头函数表达式。
#
使 staticConstructorDummyResult
成为私有的 - 现在应该可以在所有主要浏览器中使用(感谢@Donald Duck)。
我需要一些在类加载时仅运行一次的东西。
如果您只是将类用作方法包,那么您就不应该使用它们。使用一个对象来代替。但是,仍然可以运行这样的代码。只需将其放在类定义之前或之后即可。
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()
当然这并不是真的必要。除了清楚地表达静态构造函数的概念之外。然而这闻起来像Java。
Felix 提出了一个很好的解决方案,将代码放在类定义之前或之后。
例如:你想预先计算一些静态成员吗?只需在类定义后分配计算结果即可!
class Foo {}
Foo.preCalculated = calculate();
function calculate() {
console.log('Do some hard work here');
return 'PRECALCULATED';
}
在 ES2022 中,我们现在有 静态初始化块,如下所示:
class Commander {
static {
// Arbitrary code goes in here and is run when the class is defined
// 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
支持:
来源: