首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何记忆TypeScript getter

如何记忆TypeScript getter
EN

Stack Overflow用户
提问于 2019-05-15 19:39:55
回答 2查看 5.4K关注 0票数 3

我正在使用以下方法使用装饰器对TypeScript getter进行记忆,但我想知道是否有更好的方法。我正在使用npm中流行的memoizee包,如下所示:

代码语言:javascript
复制
import { memoize } from '@app/decorators/memoize'

export class MyComponent {

  @memoize()
  private static memoizeEyeSrc(clickCount, maxEyeClickCount, botEyesDir) {
    return clickCount < maxEyeClickCount ? botEyesDir + '/bot-eye-tiny.png' : botEyesDir + '/bot-eye-black-tiny.png'
  }

  get leftEyeSrc() {
    return MyComponent.memoizeEyeSrc(this.eyes.left.clickCount, this.maxEyeClickCount, this.botEyesDir)
  }
}

而memoize装饰器是:

代码语言:javascript
复制
// decorated method must be pure
import * as memoizee from 'memoizee'

export const memoize = (): MethodDecorator => {
  return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
    const func = descriptor.value
    descriptor.value = memoizee(func)
    return descriptor
  }
}

有没有一种方法可以不用在MyComponent中使用两个单独的函数,而直接将装饰器添加到TypeScript getter中?

这里的一个考虑因素是修饰函数必须是纯的(在这个场景中),但是如果你有一个不能满足这个问题的答案,你可以随意忽略它,因为我对如何处理这个问题有普遍的兴趣。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-05-15 20:19:06

装饰器可以扩展为同时支持原型方法和getter:

代码语言:javascript
复制
export const memoize = (): MethodDecorator => {
  return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
    if ('value' in descriptor) {
      const func = descriptor.value;
      descriptor.value = memoizee(func);
    } else if ('get' in descriptor) {
      const func = descriptor.get;
      descriptor.get = memoizee(func);
    }
    return descriptor;
  }
}

并直接在getter上使用:

代码语言:javascript
复制
  @memoize()
  get leftEyeSrc() {
    ...
  }
票数 6
EN

Stack Overflow用户

发布于 2019-05-16 01:58:28

基于@estus的回答,这是我最终想出来的:

代码语言:javascript
复制
@memoize(['this.eyes.left.clickCount'])
get leftEyeSrc() {
  return this.eyes.left.clickCount < this.maxEyeClickCount ? this.botEyesDir + '/bot-eye-tiny.png' : this.botEyesDir + '/bot-eye-black-tiny.png'
}

而memoize装饰器是:

代码语言:javascript
复制
// decorated method must be pure when not applied to a getter

import { get } from 'lodash'
import * as memoizee from 'memoizee'

// noinspection JSUnusedGlobalSymbols
const options = {
  normalizer(args) {
    return args[0]
  }
}

const memoizedFuncs = {}

export const memoize = (props: string[] = []): MethodDecorator => {
  return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
    props = props.map(prop => prop.replace(/^this\./, ''))
    if ('value' in descriptor) {
      const valueFunc = descriptor.value
      descriptor.value = memoizee(valueFunc)
    } else if ('get' in descriptor) {
      const getFunc = descriptor.get
      // args is used here solely for determining the memoize cache - see the options object
      memoizedFuncs[propertyKey] = memoizee((args: string[], that) => {
        const func = getFunc.bind(that)
        return func()
      }, options)
      descriptor.get = function() {
        const args: string[] = props.map(prop => get(this, prop))
        return memoizedFuncs[propertyKey](args, this)
      }
    }
    return descriptor
  }
}

这允许传递一个字符串数组,其中确定哪些属性将用于memoize缓存(在本例中,只有1个prop - clickCount -是变量,其他2个是常量)。

memoizee选项声明只有arg到memoizee((args: string[], that) => {...})的第一个数组用于记忆目的。

我还在试着弄明白这段代码有多美!今天一定过得很愉快。感谢我的朋友和救世主叶斯华:)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56148490

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档