0

I have a serious problem in my code. I have a building whose level can be increased by clicking on the button "improve". The button is created in the constructor. When I call the function with the button I get an error message that tells me that "this.price" is undefined. If I call this function by writing it in the code then "this.price" is known. How can I solve this problem?

<html>
 <body>
  <span id="buildings"></span>
  <script>
   var cookies = 0;
   var cookies_produced = 0;
   var altogether_productivity = 0; // counts productivity of buildings except clicker
   
   var cookies_display = document.getElementById("cookies");
   var cookies_produced_display = document.getElementById("cookies_produced");
   
   var buildings = document.getElementById("buildings");
   
   class Building
   {
    constructor(name, productivity, price)
    {
     this.name = name;
     this.level = 0;
     this.price = price;
     this.productivity = productivity;
   
     // variables for displaying
     // definition of areas
     this.area = document.createElement("span");
     this.area.id = name;
   
     this.level_display = document.createElement("span");
     this.level_display.id = this.name + "_level";
   
     this.productivity_display = document.createElement("span");
     this.productivity_display.id = this.name + "_productivity";
   
     this.price_display = document.createElement("span");
     this.price_display.id = this.name + "_price";
   
     this.button = document.createElement("button");
     this.button.innerHTML = "Improve";
           this.button.onclick = this.improve;
   
     // put together
     this.area.append(document.createTextNode(name + " Level: "));
     this.area.append(this.level_display);
     this.area.append(document.createElement("br"));
   
     this.area.append(document.createTextNode("Cookies per Second: "));
     this.area.append(this.productivity_display);
     this.area.append(document.createElement("br"));
   
     this.area.append(document.createTextNode("Improvement Price: "));
     this.area.append(this.price_display);
     this.area.append(document.createElement("br"));
   
     this.area.append(this.button);
     this.area.append(document.createElement("br"));
     this.area.append(document.createElement("br"));
    }
    
       improve()
       {
           console.log("cookies" + cookies);
           console.log(this.price);
           if(cookies >= this.price)
           {
               cookies -= this.price;
               this.level += 1;
               this.price *= 2;
               altogether_productivity += this.productivity;
           }
           else
           {
               alert("Not enough cookies!");
           }
       }
   
    renew_display()
    {
     this.level_display.innerHTML = this.level;
     this.productivity_display.innerHTML = this.get_production_value();
     this.price_display.innerHTML = this.price;
    }
   
   
    set_visible()
    {
     buildings.append(this.area);
     this.renew_display();
    }
   
    get_production_value()
    {
     return this.level * this.productivity;
    }
   
    produce()
    {
     cookies += this.get_production_value();
    }
   }

   var building = new Building("Building", 5, 1000)
   building.set_visible();
   building.improve();
  </script>
 </body>
</html>
Henry Weinert
  • 261
  • 3
  • 13

2 Answers2

2

Problem

Your function improve is not in the same scope with the class.

In JavaScript, functions are objects, and the value of "this" depends on how a function is called. There is a related question about JavaScript's this vs Java's this.

You can read more about JavaScript's this here.


Solution

I suggest you to bind this to improve as follows:

this.improve = this.improve.bind(this);

bind(param) works by creating a new function with this set to param when called. You can read more about it here.

Community
  • 1
  • 1
Benjamin Seche
  • 316
  • 2
  • 17
1

In constructor add this line: this.improve = this.improve.bind(this);. This is happening because of scoping. After click event this inside of improve method contain actual click event not this of a Building class

Taras Danyliuk
  • 256
  • 1
  • 11