class-static-block 提案于 2021.9.1 进入 stage4,是一个基于 Class 加强的提案。
本周咱们联合 ES2022 feature: class static initialization blocks 这篇文章一起讨论一下这个个性。
概述
为什么咱们须要 class static block 这个语法呢?其中一个起因是对 Class 动态变量的灵便赋值需要。以上面为例,咱们想在 Class 外部对动态变量做批量初始化,就不得不写一个无用的 _
变量用来做初始化的逻辑:
class Translator {
static translations = {
yes: 'ja',
no: 'nein',
maybe: 'vielleicht',
};
static englishWords = [];
static germanWords = [];
static _ = initializeTranslator(// (A)
this.translations, this.englishWords, this.germanWords);
}
function initializeTranslator(translations, englishWords, germanWords) {for (const [english, german] of Object.entries(translations)) {englishWords.push(english);
germanWords.push(german);
}
}
而且咱们为什么把 initializeTranslator
写在里面呢?就因为在 Class 外部不能写代码块,但这造成一个重大的问题,是内部函数无法访问 Class 外部属性,所以须要做一堆干燥的传值。
从这个例子看出,咱们为了自定义一段动态变量初始化逻辑,须要做出两个斗争:
- 在内部定义一个函数,并承受大量 Class 成员变量传参。
- 在 Class 外部定义一个无意义的变量
_
用来启动这个函数逻辑。
这切实太没有代码谋求了,咱们在 Class 外部做掉这些逻辑不就简洁了吗?这就是 class static block 个性:
class Translator {
static translations = {
yes: 'ja',
no: 'nein',
maybe: 'vielleicht',
};
static englishWords = [];
static germanWords = [];
static {// (A)
for (const [english, german] of Object.entries(this.translations)) {this.englishWords.push(english);
this.germanWords.push(german);
}
}
}
能够看到,static
关键字前面不跟变量,而是间接跟一个代码块,就是 class static block 语法的特色,在这个代码块外部,能够通过 this
拜访 Class 所有成员变量,包含 #
公有变量。
原文对这个个性应用介绍就完结了,最初还提到一个细节,就是执行程序。即所有 static
变量或区块都按程序执行,父类优先执行:
class SuperClass {static superField1 = console.log('superField1');
static {assert.equal(this, SuperClass);
console.log('static block 1 SuperClass');
}
static superField2 = console.log('superField2');
static {console.log('static block 2 SuperClass');
}
}
class SubClass extends SuperClass {static subField1 = console.log('subField1');
static {assert.equal(this, SubClass);
console.log('static block 1 SubClass');
}
static subField2 = console.log('subField2');
static {console.log('static block 2 SubClass');
}
}
// Output:
// 'superField1'
// 'static block 1 SuperClass'
// 'superField2'
// 'static block 2 SuperClass'
// 'subField1'
// 'static block 1 SubClass'
// 'subField2'
// 'static block 2 SubClass'
所以 Class 内容许有多个 class static block,父类和子类也能够有,不同执行程序后果必定不同,这个选择权交给了使用者,因为执行程序和书写程序统一。
精读
联合提案来看,class static block 还有一个动机,就是给了一个拜访公有变量的机制:
let getX;
export class C {
#x
constructor(x) {this.#x = { data: x};
}
static {
// getX has privileged access to #x
getX = (obj) => obj.#x;
}
}
export function readXData(obj) {return getX(obj).data;
}
实践上内部无论如何都无法访问 Class 公有变量,但下面例子的 readXData
就能够,而且不会运行时报错,起因就是其整个流程都是非法的,最重要的起因是,class static block 能够同时拜访公有变量与全局变量,所以能够利用其做一个“内外夹攻”。
不过我并不感觉这是一个好点子,反而像一个 “BUG”,因为任何对规定的冲破都会为可维护性埋下隐患,除非这个个性用在稳固的工具、框架层,用来做一些便利性工作,最终晋升了利用编码的体验,这种用法是能够承受的。
最初要意识到,class static block 实质上并没有减少新性能,咱们齐全能够用一般动态变量代替,只是写起来很不天然,所以这个个性能够了解为对缺点的补充,或者是语法欠缺。
总结
总的来说,class static block 在 Class 内创立了一个块状作用域,这个作用域内领有拜访 Class 外部公有变量的特权,且这个块状作用域仅在引擎调用时初始化执行一次,是一个比拟不便的语法。
原文下方有一些拥护声音,说这是对 JS 的复杂化,也有诸如 JS 越来越像 Java 的声音,不过我更同意作者的观点,也就是 Js 中 Class 并不是全副,当初越来越多代码应用函数式语法,即使应用了 Class 的场景也会存在大量函数申明,所以 class static block 这个提案对开发者的感知实际上并不大。
探讨地址是:精读《class static block》· Issue #351 · dt-fe/weekly
如果你想参加探讨,请 点击这里,每周都有新的主题,周末或周一公布。前端精读 – 帮你筛选靠谱的内容。
关注 前端精读微信公众号
<img width=200 src=”https://img.alicdn.com/tfs/TB165W0MCzqK1RjSZFLXXcn2XXa-258-258.jpg”>
版权申明:自在转载 - 非商用 - 非衍生 - 放弃署名(创意共享 3.0 许可证)