1

Is there a better way to write this? Ideally I want to write pre_calculated_h inside the object literal, somehow.

const obj = {
  long_calc_f(x) {return 5*x}, //Some time consuming calculation
  g(x) {return x + 2},
}
obj.pre_calculated_h = function(n) {
  const pre_calculated_values = []

  for (var i = 0; i < n; i++) pre_calculated_values.push(this.g(this.long_calc_f(i)))

  return function(x) {return pre_calculated_values[x]}
}.call(obj, 20)
Shuri2060
  • 729
  • 6
  • 21
  • Sounds like you try to reinvent memoization. – Wiktor Zychla Feb 25 '21 at 18:39
  • Yeah, this is memoization – Shuri2060 Feb 25 '21 at 18:41
  • The thing is, it's not quite --- in the actual application, I'm using the `long_calc` function in the `pre_calc` function to make a slightly different calculation... if that makes sense – Shuri2060 Feb 25 '21 at 18:51
  • 1
    I have a long calculation `f(x)`, but am only interested in storing `h(x) = g(f(x))`. Edited the question to illustrate this – Shuri2060 Feb 25 '21 at 18:54
  • Why do all this in the object literal? Why not write a class with a constructor? – Wyck Feb 25 '21 at 18:58
  • I'm only using it once. I could (if that's thought to be the best solution) – Shuri2060 Feb 25 '21 at 18:59
  • Your question says "if I want to reuse that function" but your most recent comment says "I'm only using it once" So which one is true? – Wyck Feb 25 '21 at 19:00
  • Edited Q. Yes, I only use the object once. My problem with the way it is written is if I rename `obj`, I have to edit the code in several places. – Shuri2060 Feb 25 '21 at 19:07
  • You could declare a function `const obj = add_precalculated_h({ ... }, 20)` where `function add_precalculated_h(obj, n) { obj.....}` mutates the argument it gets. No need to sync variable names – Yury Tarabanko Feb 25 '21 at 19:15
  • @Wyck Yes I read that beforehand, and none of the solutions seem to quite get there for this problem. The closest for me is the getter which does the calculation first time it is called. So I could use that and immediately call it to pre-calc immediately after creating that object, I guess. – Shuri2060 Feb 25 '21 at 19:18
  • FWIW: (since this is already closed) here's the constructor technique: `let obj = new (function (n) { this.long_calc_f = x => x * 5; this.g = x => x + 2; let pre_calculated_values = []; for (var i = 0; i < n; i++) pre_calculated_values.push(this.g(this.long_calc_f(i))); this.pre_calculated_h = x => pre_calculated_values[x]; })(20);` – Wyck Feb 25 '21 at 19:31
  • my bad yes, I just realised that myself. Thanks for the suggestion! – Shuri2060 Feb 25 '21 at 19:37

1 Answers1

0

You can define a getter and reference object as this w/o passing it explicitly. Not sure if it is by any means better :) But the downside you will need to reference property name twice.

const obj = {
  long_calc_f(x) {
    return 5 * x
  }, //Some time consuming calculation
  g(x) {
    return x + 2
  },

  get pre_calculated_h() {
    console.log(`Precalculating`)
    const pre_calculated_values = []

    for (var i = 0; i < 20; i++) pre_calculated_values.push(this.g(this.long_calc_f(i)))

    const value = function(x) {
      return pre_calculated_values[x]
    };

    Object.defineProperty(this, 'pre_calculated_h', {
      enumerable: true,
      writable: false,
      value
    });

    return value
  }
}

console.log(obj.pre_calculated_h(1), obj.pre_calculated_h(3), obj.pre_calculated_h(15))
Yury Tarabanko
  • 44,270
  • 9
  • 84
  • 98