javascript objects - retrieve child class variable

javascript class inheritance
javascript inheritance w3schools
javascript class inheritance es6
class extends javascript
types of inheritance in javascript
javascript extend object
javascript instantiate class
multiple inheritance in javascript

The question has a javascript and coffescript jsfiddle at the bottom of the question.

Both fiddle include explanatory comments that needs to be read in a specific order, it print out values to the console when you click on product or submit div, in addition I give you this basic explanation of my issue.

  • I have 3 Javascript classes Purchase, Product and Item
  • One Purchase has many Products, One Product has many Items
  • The Purchase object sets a click event handler on the $('submit') and onClick() will post the items data to my backend api
  • This is the data format accepted from my backend api

    {
      'purchase' => {
        'items_attributes' => {
          '0' => {
            'purchase_id' => '1'
          },
          '1' => {
            'purchase_id' => '2'
          }
        }
      }
    }
    

My coffeescript jsfiddle is at the following link

Click below to open the javascript fiddle.

(function() {
  var Item, Product, Purchase,
    bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

  Purchase = (function() {
    function Purchase() {
      /* on $(document).ready a new Purchase is created */ 
      this.submit = $('#submit');
      /* for each div.product a new Product instance is created */
      this.products = $.map($('.product'), function(product, i) {
        return new Product(product);
      });
      / @onSubmit() */
      
      /* Comment 3) 
      My issue here is how to I access the this.items from the Purchase class and call serialize()?
      onSubmit: function () {
        @submit.click(function(){console.log(Product.serialize())};
      }     */
    }

    return Purchase;

  })();

  Product = (function() {
    Product.items = [];

    function Product(product) {
      this.product = $(product);
      this.id = this.product.data("id");
      this.submit = $('#submit');
      this.setEvent();
      this.onSubmit();
    }

    Product.prototype.setEvent = function() {
      return this.product.click((function(_this) {
        return function() {
          /* Comment 1)
             Product.items is a class variable of Product, because I need to access it from the Purchase class and send post request. When the user clicks on the $('submit') button*/
          Product.items.push(new Item(_this.id));
          return console.log(Product.items);
        };
      })(this));
    };

    Product.prototype.onSubmit = function() {
      return this.submit.click(function() {
      /* Comment 2) 
      This works as you can see, but we have 4 products and this operation will 
      be performed 4 times. I want to achieve this in the Purchase object so it is perfomed only once, by creating a sumit event handler in Purchase */      
        return console.log(Product.serialize());
      });
    };

    Product.serialize = function() {
      var item;
      return {
        items_attributes: (function() {
          var j, len, ref, results;
          ref = Product.items;
          results = [];
          for (j = 0, len = ref.length; j < len; j++) {
            item = ref[j];
            results.push(item.serialize());
          }
          return results;
        })()
      };
    };

    return Product;

  })();

  Item = (function() {
    function Item(product_id) {
      this.product_id = product_id;
      this.serialize = bind(this.serialize, this);
    }

    Item.prototype.serialize = function() {
      return {
        product_id: this.product_id.toString()
      };
    };

    return Item;

  })();

  $(document).ready(function() {
    return new Purchase();
  });

}).call(this);
.console {
  background-color: grey;
  color: white;
  height: 500px;
}      # I print to the console Product.items 

h4 {
  color: red;
  width: 100%;
  text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<ul>
  <li class="product" data-id="1">Product 1</li>
  <li class="product" data-id="2">Product 2</li>
  <li class="product" data-id="3">Product 2</li>
  <li class="product" data-id="4">Product 3</li>
  <li class="product" data-id="5">Product 4</li>
  <div id="submit">Create Purchase</div>
</ul>

<h4>check logs by opening the console</h4>

Class inheritance, If we call super.method() then, the engine needs to get the method from the prototype of the current object. But how  To extend a class: class Child extends Parent: That means Child.prototype.__proto__ will be Parent.prototype, so methods are inherited. When overriding a constructor: We must call parent constructor as super() in Child constructor before using this. When overriding another method: We can use super.method() in a Child method to call Parent method.

I'm a fan of the Active Model Serializer gem which is now a part of Rails. I would try expanding this pattern into your coffeescript by adding a serialize method to all of your classes, and call these when you pass data to your server.

I'm not sure on your plans for the Item class, so here is a simple mockup with the proposed serialize method:

class Item
  constructor: (@purchase, @product, @quantity) ->

  serialize: =>
    purchase_id: @purchase.id.toString()
    product_id: @product.id.toString()
    quantity: parseInt(@quantity)

Given that your purchase class will have an array of @items, then the Purchase's serialize method would look something like this:

serialize: =>
  items_attributes: (item.serialize() for item in @items)

And your ajax post would then use the serialize method:

$.ajax
   url: "/items"
   method: "POST"
   dataType: "json"
   data: 
     purchase: @serialize()
   error: (jqXHR, textStatus, errorThrown) ->
   success: (data, textStatus, jqXHR) ->

Then you should get a JSON post body of

'purchase' => {
  'items_attributes' => [
    {
      'purchase_id' => '1'
    },
    {
      'purchase_id' => '2'
    }
  ]
}

which you can use within your rails controller via strong params:

params.require(:purchase).permit(item_attributes: [:purchase_id])

Inheritance in JavaScript, At this point you should understand JavaScript object and OOP basics, prototypes and prototypal inheritance, how to We need to get Teacher() to inherit the methods defined on Person() A getter returns the current value of the variable and its corresponding setter changes the value of the variable to the  The cStringArray variable will contain the Class corresponding to a two-dimensional array of String (i.e. identical to String[][].class). TYPE Field for Primitive Type Wrappers The .class syntax is a more convenient and the preferred way to obtain the Class for a primitive type; however there is another way to acquire the Class .

You can simply bind the event inside your Purchase object when it is initialized.

this.submit.click(function() {
    return console.log(Product.serialize());
});

Working Snippet: I have commented out onSubmit of Product.

(function() {
  var Item, Product, Purchase,
    bind = function(fn, me) {
      return function() {
        return fn.apply(me, arguments);
      };
    };

  Purchase = (function() {
    function Purchase() {
      /* on $(document).ready a new Purchase is created */
      this.submit = $('#submit');
      /* for each div.product a new Product instance is created */
      this.products = $.map($('.product'), function(product, i) {
        return new Product(product);
      });
      / @onSubmit() */

      /* Comment 3) 
      My issue here is how to I access the this.items from the Purchase class and call serialize()?
      onSubmit: function () {
        @submit.click(function(){console.log(Product.serialize())};
      }     */
      this.submit.click(function() {
        return console.log(Product.serialize());
      });
    }

    return Purchase;

  })();

  Product = (function() {
    Product.items = [];

    function Product(product) {
      this.product = $(product);
      this.id = this.product.data("id");
      this.submit = $('#submit');
      this.setEvent();
      // this.onSubmit();
    }

    Product.prototype.setEvent = function() {
      return this.product.click((function(_this) {
        return function() {
          /* Comment 1)
             Product.items is a class variable of Product, because I need to access it from the Purchase class and send post request. When the user clicks on the $('submit') button*/
          Product.items.push(new Item(_this.id));
          return console.log(Product.items);
        };
      })(this));
    };

    // Product.prototype.onSubmit = function() {
    //   return this.submit.click(function() {
    //     /* Comment 2) 
    //     This works as you can see, but we have 4 products and this operation will 
    //     be performed 4 times. I want to achieve this in the Purchase object so it is perfomed only once, by creating a sumit event handler in Purchase */
    //     return console.log(Product.serialize());
    //   });
    // };

    Product.serialize = function() {
      var item;
      return {
        items_attributes: (function() {
          var j, len, ref, results;
          ref = Product.items;
          results = [];
          for (j = 0, len = ref.length; j < len; j++) {
            item = ref[j];
            results.push(item.serialize());
          }
          return results;
        })()
      };
    };

    return Product;

  })();

  Item = (function() {
    function Item(product_id) {
      this.product_id = product_id;
      this.serialize = bind(this.serialize, this);
    }

    Item.prototype.serialize = function() {
      return {
        product_id: this.product_id.toString()
      };
    };

    return Item;

  })();

  $(document).ready(function() {
    return new Purchase();
  });

}).call(this);
.console {
  background-color: grey;
  color: white;
  height: 500px;
}

h4 {
  color: red;
  width: 100%;
  text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<ul>
  <li class="product" data-id="1">Product 1</li>
  <li class="product" data-id="2">Product 2</li>
  <li class="product" data-id="3">Product 2</li>
  <li class="product" data-id="4">Product 3</li>
  <li class="product" data-id="5">Product 4</li>
  <button type="button" id="submit">Create Purchase</button>
</ul>

<h4>check logs by opening the console</h4>

Object.getOwnPropertyNames(), Now I have Class B variables which I also need to use in Class A. And also one another Class C, Class A add in Longer, more detailed explanation: Classes don't have variables -- objects do. So to get to your question. In Java, it is possible to inherit attributes and methods from one class to another. We group the "inheritance concept" into two categories: subclass (child) - the class that inherits from another class; superclass (parent) - the class being inherited from; To inherit from a class, use the extends keyword.

Can I use a child class variables in its parent class?, The reference variable of the Parent class is capable to hold its object reference as well as its child object reference. In Java, methods are virtual by default (See  JavaScript Objects. ❮ Previous Next ❯. In real life, a car is an object. A car has properties like weight and color, and methods like start and stop: All cars have the same properties, but the property values differ from car to car. All cars have the same methods, but the methods are performed at different times.

Parent and Child classes having same data member in Java , HTML · CSS · JavaScript · PHP · JQuery If the methods are present in SuperClass, but overridden by SubClass, it will be and variables) of the object defined by the superclass or subclass. Now when we try to get elements of arraylist using ArrayList.get(int index) method then we must use Object reference, as in this  Stores class methods, such as sayHi, in User.prototype. After new User object is created, when we call its method, it’s taken from the prototype, just as described in the chapter F.prototype. So the object has access to class methods.

Referencing Subclass objects with Subclass vs Superclass , When we create a variable in both parent and child class with the class reference which is holding a child class's object then what do we get? JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax does not introduce a new object-oriented inheritance model to JavaScript.

Comments
  • are you sure you want an object with string keys "0" and "1" instead of an array?. And where is the @products.click handler in your code? Did you mean @submit.click ?
  • @Caffeinated.tech thanks a lot! I was thinking of doing something like @products.click => new Item inside the Purchase class and then save those instances inside a class Purchase; @items = ... so that when I do @submit.click I can perform the AJAX by passing all the @items. The format required by rails params is items_attributes => {"0".. etc.. but do you think I can use an array? Because It needs to be stringified and how is going to work with the format? thanks a lot
  • thanks for you answer. It helped me better understanding this problem, given my need to learn Javascript/Coffescript and to better understand this programming languages. I decided to post a bounty of 200 for this question (which I reviewed both for javascript and coffescript). I though of notifying you. Thanks a lot
  • @FabrizioBertoglio You should post a new question regarding your data structure, rather than editing and replacing the original question. Now my answer won't be useful to anyone else coming along in future with a similar question and seems off
  • I can still give you the bounty of 200, the coffescript version of the question is still available on JSFiddle jsfiddle.net/b1tqkh00/1179 and I already implemented a solution to this problem as suggested from @Munim Munna. You can see my commit history which clearly explains what I implemented github.com/fabriziobertoglio1987/sprachspiel/commits/… the functionality works fine, but a better Coffescript solution can posted and rewarded. If you wish once the bounty is over I will remove the Javascript fiddle and replace it with the coffescript code
  • this is the specific commit that Implemented the solution for this problem github.com/fabriziobertoglio1987/sprachspiel/commit/… From the dry point of view I like your question, I did commit the above solution before @Munim Munna gave me this solution, but he was kind to explain me that I could use Product.items inside the Purchase class, improving my code. I am in debt with both of you.
  • ok, so I can call Product.serialize() inside the Purchase object ?! I did solve this github.com/fabriziobertoglio1987/sprachspiel/commit/… but saving the items as a Purchase.items class variable, but your solution is dry and better so I'll try this in the next days and let you know. I am still using a lot of @Caffeinated.tech solution so I need to understand who helped me more and give him the bounty.. Thanks a lot !
  • Yes you can access it because it is declared as a variable in the outer scope. Read this to better understand JavaScript scopes, understanding scopes will give you a head-start in learning JavaScript.
  • yes. I believe you are right. That is the key to the solution, understanding how this objects are connected, while still I wonder how I could access the @purchase from the @product instance. Is also that about scopes or should I actually send as input the @purchase variable in the new Product(@purchase) constructor..? Thanks a lot .. this is key to my understanding of this issue
  • If you have have only a single purchase object, then scope is OK, if you have multiple of them, then you need to link products with purchase just the way you are thinking, and purchase should contain a list of products. And if you click on the same item twice they are being listed twice, you need to avoid it. Try it and post updates to the question if you get stuck.