[英]javascript and memoized getters
这篇文章描述了 getter 。 它有一个部分“智能/自我覆盖/懒惰的getter”我不清楚,默认情况下getter是“记忆化”还是我应该自己实现这个功能
例如
class Foo() {
get boo() {
this._boo = this._boo || new Boo();
return this._boo;
}
}
或者我可以写:
class Foo() {
get boo() {
return new Boo();
}
}
有相同的结果?
那篇文章中最有趣的一点是Smart / self-overwriting / lazy getters ,它提供了这种技术:
class Foo { get boo() { delete this.boo; return this.boo = new Boo(); } }
有了这个,你的Foo
对象不会经历创建它们的boo
属性的麻烦,直到你要求它。 然后它被创建一次,对它的进一步请求只是返回相同的对象。 如果new Boo()
以某种方式创建资源密集型并且通常不需要,那么这是有道理的。
理论上,您可以扩展它以允许您删除当前版本并在下次访问时重新创建它。 但这需要更多的代码,而且可能是相当罕见的需求。
vrugtehagel的评论正确地指出,上述技术虽然适用于普通对象,但不适用于类。
这是一个有效的变体:
class Boo { static counter = 0 constructor () { this.x = ++Boo.counter console .log (`creating Boo(${this.x})`) } } class Foo { get boo () { Object .defineProperty ( this, "boo", { value: new Boo(), writable: false} ) return this .boo; } } const f = new Foo() console .log (f.boo) console .log (f.boo) // no 'creating Boo' log, Boo constructor only created once
不,JavaScript 中没有对记忆化 getter 的语言级支持。 在您的第二个示例中,每次访问boo
时都会创建一个新对象。
您可以自由添加备忘录,例如
非记忆,
class NonMemoized {
constructor(prefix) {
this.prefix = prefix;
}
get myFunc() {
return this.prefix + Math.random().toString();
}
}
let nonMemoized = new NonMemoized('new number each time ');
console.log(nonMemoized.myFunc);
console.log(nonMemoized.myFunc);
记忆化,非常适合当您想创建一个对象并始终返回相同的对象时(但不想在构造函数中创建,因为可能没有必要一直或其他原因)
class MemoizedManually {
constructor(prefix) {
this.prefix = prefix;
}
get myFunc() {
return this._myFunc_ = this._myFunc_ || this.prefix + Math.random().toString();
}
}
let memoizedManually = new MemoizedManually('same number ');
console.log(memoizedManually.myFunc);
console.log(memoizedManually.myFunc);
最后,如果你有一堆函数想要记住但又不想重复this.x = this.x || something computation
每个函数中的this.x = this.x || something computation
(你真的不应该重复,因为它不是myFunc
真正的工作来记忆自己:
class Memoized {
constructor(prefix) {
this.prefix = prefix;
}
get myFunc() {
return this.prefix + Math.random().toString();
}
}
const memoizeGetter = (clazz, functionName) => {
let func = Object.getOwnPropertyDescriptor(clazz.prototype, functionName);
let cacheKey = `_${functionName}-cache_`;
Object.defineProperty(clazz.prototype, functionName, {
get: function () {
return this[cacheKey] = this[cacheKey] || func.get.call(this);
}
});
};
memoizeGetter(Memoized, 'myFunc');
let memoized = new Memoized('also same number ');
console.log(memoized.myFunc);
console.log(memoized.myFunc);
getter 的好处是它们不接受参数,因此您不必担心...args
,但确实需要担心绑定this
考虑这个代码:
class Person {
static get SHORT() { return 0; }//rvalue
}
对
class Person {}
Person.SHORT = 0;//lvalue
虽然两者都返回相同的结果,但后者实际上更快(因为它避免了函数调用开销); 尽管 js 引擎可以进行优化,使一个无效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.