0

In the below code when I console the values of calculateTips(), I am getting the following error

Uncaught TypeError: Cannot set property '0' of undefined

let tipCal = {
  bills: [124, 48, 268, 180, 42],
  calculateTips: function() {
    this.tips = [];
    this.finalValue = [];
    (this.bills).forEach(function(item, index) {
      if (item < 50) {
        this.tips[index] = (item * .2);
      } else if (item >= 50 && item < 200) {
        this.tips[index] = (item * .15);
      } else {
        this.tips[index] = (item * .1);
      }
    });
    return this.tips;

  }
}

I am unable to understand why I am getting this error because according to me I am doing the right thing. Please help.

Jatin Parmar
  • 2,759
  • 5
  • 20
  • 31
  • `this` inside of your `.forEach` function isn't referring to your object. You can use an arrow function instead – Nick Parsons Dec 16 '19 at 05:33
  • Does this answer your question? [How to access the correct \`this\` inside a callback?](https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback) – Nick Parsons Dec 16 '19 at 05:34

4 Answers4

1

A couple of things to note. First, using index notation instead of Array.prototype.push isn't very common, as far as I've seen. Since you're building this.tips from scratch, you can use this.tips.push(...). Using push can sometimes have better performance as well. See here: Why is array.push sometimes faster than array[n] = value?

Secondly, yes, the use of a function changes the context of this, so this inside your forEach callback is referring to the callback function and not tipCal. Using an arrow function as has been suggested will retain the context of this.

Matt U
  • 4,970
  • 9
  • 28
0

You can achieve your result by doing this. Use it according to your need.

var num = 10,
  dynar = [...Array(num)].map((_,i) => ++i+"");
console.log(dynar);

Output: [ "1", "2", "3", "4", "5", "6", "7", "8",
"9", "10" ]

waqarahmad
  • 41
  • 3
0

Replace .forEach callback function with =>(arrow) function

Try this:

  let tipCal = {
    bills: [124, 48, 268, 180, 42],
    calculateTips: function () {
      this.tips = [];
      this.finalValue = [];
      (this.bills).forEach((item, index)=> {
        if (item < 50) {
          this.tips[index] = (item * .2);
        } else if (item >= 50 && item < 200) {
          this.tips[index] = (item * .15);
        } else {
          this.tips[index] = (item * .1);
        }
      });
      return this.tips;

    }
  }
  console.log(tipCal.calculateTips())
Saurabh Agrawal
  • 7,581
  • 2
  • 27
  • 51
0

I think this because function inside a function change the this keyword.

the .forEach(function(item, index) { live inside calculateTips: function() {. Try to use the arrow function, so it's will be .forEach((item, index) => {.

The arrow function will not change the this keyword.

So it will return..

(5) [18.599999999999998, 9.600000000000001, 26.8, 27, 8.4]

Septiana Yoga
  • 21
  • 1
  • 7