1

i'm trying to find a solution to this exercise:

Implement the calculate function that adds an object that gives the ability to do the four mathematical operations (addition, subtraction, multiplication and division) on the same number and finally print out the result.

function calculate() {

}

const calculator = calculate();
calculator.add(2).add(4).multiply(3).sub(1).sub(3).divide(2).printResult(); // result will be: 7
console.log(calculator)

so, what is the right way to solve this (and if you can add comment will be appreciated

2 Answers2

3

no need to put so many this and function...

in this way you have a closure value.
=> calc_00.val = 20;
will not change the result (it just add a new property if jso is not freeze ) or throw an error in strict mode

"use strict";

function calculate( initVal = 0 )  // default value is zero
  {
  let
    val = initVal    // closure value
  , jso =
    { add(v)         { val += v; return this }
    , sub(v)         { val -= v; return this }
    , multiply(v)    { val *= v; return this }
    , divide(v)      { val /= v; return this }
    , printResult()  { return val }
    }
  Object.freeze(jso)
 
  return jso
  }

const
  calc_00 = calculate()
, calc_10 = calculate(10)
  ;

// calc_00.yop = ()=>null; // Uncaught TypeError: can't define property "yop": Object is not extensible
// calc_00.sub = ()=>null; // Uncaught TypeError: "sub" is read-only
// calc_00.val = 20;       // Uncaught TypeError: can't define property "val": Object is not extensible

calc_00.add(2).add(4).multiply(3).sub(1).sub(3).divide(2);
calc_10.add(10).multiply(3);

console.log( calc_00.printResult(), calc_10.printResult() ) // 7 , 60
Mister Jojo
  • 20,093
  • 6
  • 21
  • 40
2

You can return the object itselft.

function calculate() {
  return {
    result: 0,
    add: function(num) {
      this.result += num;
      return this;
    },
    sub: function(num) {
      this.result -= num;
      return this;
    },
    multiply: function (num) {
      this.result *= num;
      return this;
    },
    divide: function (num) {
      this.result /= num;
      return this;
    },
    printResult: function () {
      return this.result;
    }
 }
};

const calculator = calculate();
const result = calculator.add(2).add(4).multiply(3).sub(1).sub(3).divide(2).printResult(); // result will be: 7
console.log(result);

Make sure to understand how this works in JavaScript. For instance, using functions is different than using arrow functions.

Reference: JavaScript this

Alternative solution using closure

function calculate() {
  let result = 0;
  return {
    add: function(num) {
      result += num;
      return this;
    },
    sub: function(num) {
      result -= num;
      return this;
    },
    multiply: function (num) {
      result *= num;
      return this;
    },
    divide: function (num) {
      result /= num;
      return this;
    },
    printResult: function () {
      return result;
    }
 }
};

const calculator = calculate();
const result = calculator.add(2).add(4).multiply(3).sub(1).sub(3).divide(2).printResult(); // result will be: 7
console.log(result);
Mirco Bellagamba
  • 950
  • 6
  • 15
  • Would it be okay to consider this to be a `closure` in JavaScript? Apologies, I'm still learning js - and, I've read about closures & understood (may be, incorrectly) that the fundamental idea of js-closures was to initialize some variable(s) only once and have it retain the value across function-calls. – jsN00b Mar 03 '22 at 15:50
  • this is exactly what i need to learn, now that i can see it visually is perfect, i will make more and more try on this – MarkLearningCode Mar 03 '22 at 15:56
  • A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function's scope from an inner function [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures). `this` is not like a closure, it is a language keyword [reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this). – Mirco Bellagamba Mar 03 '22 at 17:13
  • Guess what happen if you change this line `const calculator = calculate();` to `const calculator = calculate(); calculator.result = 100;` ? : you need a closure ;) – Mister Jojo Mar 03 '22 at 17:32
  • Yes, closures provide better encapsulation. I thought it was not the point of the problem. However I've updated the answer with a closure based alternative. – Mirco Bellagamba Mar 03 '22 at 20:51