1

I have an object as follows

var shop = {
    costPrice: function() {
        return 100;
    },
    sellingPrice: function() {
        var calculateProfit = function() {
            return this.costPrice() * 0.2;
        }

        return this.costPrice() + calculateProfit();
    }
};

console.log(shop.sellingPrice());

But this gives me the following error

objects.html:16 Uncaught TypeError: this.costPrice is not a function
    at calculateProfit (objects.html:16)
    at Object.sellingPrice (objects.html:19)
    at objects.html:22

Not sure what I am doing wrong as costPrice is a function

Amir MB
  • 3,233
  • 2
  • 10
  • 16
  • I think that you can not (to be verified). You should declare the object as a class instance so that you could use something like `this.costPrice()` – Guillaume Munsch Aug 17 '21 at 15:51
  • 1
    You can make calculateProfit an arrow function. `var calculateProfit = () => this.costPrice() * 0.2;` – Wyck Aug 17 '21 at 15:51
  • `this` is then the object itself? Didn't know that, that's nice! – Guillaume Munsch Aug 17 '21 at 15:52
  • @GuillaumeMunsch, sort of. Please check out https://stackoverflow.com/questions/31095710/methods-in-es6-objects-using-arrow-functions for more details on what `this` means in an arrow function.. – Wyck Aug 17 '21 at 15:54
  • Ty! Just went through this one https://stackoverflow.com/a/7043822/3683576 :) – Guillaume Munsch Aug 17 '21 at 15:54
  • @Wyck can you explain why using the arrow function for `calculateProfit` works? Is it because in arrow function `this` will refer to the object and not the `costPrice` function? – ThatRandomDeveloper Aug 17 '21 at 15:59
  • @ThatRandomDeveloper, that has been explained elsewhere. e.g. [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this): _ES2015 introduced arrow functions which don't provide their own `this` binding (it retains the `this` value of the enclosing lexical context)._ – Wyck Aug 17 '21 at 16:06

3 Answers3

3

calculateProfit must be an arrow function

var shop = {
            costPrice : function() {
                return 100;
            },
            sellingPrice : function() {
                var calculateProfit = () => {
                    return this.costPrice() * 0.2;
                }

                return this.costPrice() + calculateProfit();
            }
        };

console.log(shop.sellingPrice());
Adil Bimzagh
  • 224
  • 1
  • 9
  • This works. But can you explain as to why this works? – ThatRandomDeveloper Aug 17 '21 at 15:54
  • Because when using `function`, `this` refers to the `window` object but when using an arrow function `this` refers to its current surrounding scope. – Adil Bimzagh Aug 17 '21 at 16:06
  • @ThatRandomDeveloper, FYI _why it works_ is explained in detail in [this documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#arrow_functions). – Wyck Aug 17 '21 at 16:16
1

Try changing these functions to be arrows:

var shop = {
            costPrice : function() {
                return 100;
            },
            sellingPrice : function() {
                var calculateProfit = () => {
                    return this.costPrice() * 0.2;
                }

                return this.costPrice() + calculateProfit();
            }
        };

console.log(shop.sellingPrice());
  • 3
    In that case, `this` will refer to whatever "this" was in scope before `shop` was defined. Try changing `sellingPrice` to be a regular `function` – smac89 Aug 17 '21 at 15:52
  • Yup, just after adding comment I realised that only `calculateProfit` should be arrow, I will fix that :D – Tomasz Staszkiewicz Aug 17 '21 at 15:54
1

var shop = {
    costPrice: function() {
        return 100;
    },
    sellingPrice: function() {
        var calculateProfit = () => this.costPrice() * 0.2;

        return this.costPrice() + calculateProfit();
    }
};

console.log(shop.sellingPrice());
Amir MB
  • 3,233
  • 2
  • 10
  • 16