我的库中有一个 JavaScript ES6 类,它使用一些私有基值来计算另一个值。
抽象简化后的情况是这样的:
class Example {
#apples;
#oranges;
#cherries;
constructor() {
this.#apples = 22;
this.#oranges = 38;
this.#cherries = 12;
}
get numOfFruits() {
return this.#apples + this.#oranges + this.#cherries;
}
}
现在我想向示例添加一个函数来计算新值,例如像这样的东西:
Example.prototype.getNumOfApplesAndOranges = function() {
return this.#apples + this.#oranges;
};
我知道你不应该访问其声明类之外的私有变量,但我认为通过向类添加方法,访问发生在类内。
但是这不起作用并且会出现错误
Uncaught SyntaxError: reference to undeclared private field or method #apples
。有什么办法可以做到这一点吗?
我已经尝试过
eval
、Proxy
和 Object.setPrototypeOf
,但这些都没有帮助。
正如其他人评论的那样,由于决定让“#”成为硬私有,似乎不可能从声明它的类块外部访问私有字段。
但是在这个解决方案的基础上我发现了一个非常hacky和糟糕的方法来解决这个问题,但它适用于我的用例,所以我将在这里分享它。
我在包含该类的脚本之前添加了一个脚本,基本上是这样做的:
<script>
const observer = new MutationObserver( (mutations) =>{
mutations.forEach(({addedNodes}) => {
[...addedNodes]
.forEach(node => {
if(node.tagName?.toLowerCase() !== "script"){
return;
}
node.innerHTML = node.innerHTML.replace(/(class Example \{)/i, "$1\nget getNumOfApplesAndOranges(){\nreturn this.#apples + this.#oranges;}\n");
observer.disconnect();
});
});
});
observer.observe(document.head, {childList: true});
document.addEventListener("DOMContentLoaded", (ev) => {
console.log((new Example()).getNumOfApplesAndOranges);
});
</script>
<script>
class Example {
#apples;
#oranges;
#cherries;
constructor() {
this.#apples = 22;
this.#oranges = 38;
this.#cherries = 12;
}
get numOfFruits() {
return this.#apples + this.#oranges + this.#cherries;
}
}
</script>
但就我而言,我必须从 DOM 中删除第二个脚本,获取第二个脚本的内容(因为它是从另一台服务器加载的),然后修改它以允许访问私有字段并将其写入新的脚本标记然后将其附加到 DOM。