Search code examples
javascriptinheritancetabsthisjavascript-objects

Javascript object inheritance when objects are properties of other objects?


I think I'm beginning to grasp the concept of inheritance when an object is created from another object, but don't understand it when an object is a property of another object. I had all of my code working using a combination of multi-dimensional arrays and objects but not in a real OOP format. Now, in trying to convert it all over to an OOP format, I have a few issues.

In the code example below:

  1. Is it possible to reference the display.index of the "parent" that contains a tab from method_1 of a tab?

  2. If display has methods, can they be invoked from within a tab method and, if so, how?

I think what I'm really trying to get to is a set up in which the objects within an object inherit from the "parent" object even though they were not created from the parent object. Is that possible and, if so, what is it called? I can accomplish the same by using arrays or objects as associative arrays, such as view[0].index, but it appears that a real OOP format ought not to need that.

I realize that I could pass display.index to the tab constructor make it a property of tab and set a tab method to a defined display method, or tab could be created from display; but the point was to try to reduce the number of methods on display and group them by the "sub"-objects to which they apply.

What is the proper way of accomplishing this?

Thank you.

function tab( id )
 {
  this.id = id;
 }

function display( i )
  {
    this.index = i;
    this.tab = new tab(1);
  }
    
 tab.prototype.method_1 = function()
   {
     // Can the display.index that contain tab be referenced here?
     // That is, apart from using view[0].index.
   };

var view = [ new display( 0 ) ];

I was trying to have each tab instance inherit the properties and methods of display and then have the tab properties and methods as own properties. The code below worked in that view.tab inherited the properties and methods of display and had the tab constructor properties as own properties, but didn't get method_1 of the constructor. I can add the methods after that but there are many and it would have to be done for each instance of tab. I haven't found a method that adds the full result of the constructor like Object.assign does with properties.

The OOP format is interesting but, at this point, I cannot tell if it is more efficient than using multi-dimensional indexes. Instead of having one function that does the same thing to all tabs in a display by operating on a variables of display[ i ].tab[ j ] or just display[ i ][ j ], I end up with separate methods for each tab instance, which are more direct since there are no logic statements testing for differences in tabs based on index j but is it really quicker when it is necessary to search through all the prototypes.

Is starting the tabs off as inheriting from display any better than just storing a reference to the this of display in each tab instance? I don't know enough to know if asking for a property through a stored reference to the this of display is quicker or slower than having a higher prototype and searching through the lower prototypes of tab upward until the inherited property is found.

An advantageseems to be that, if I can get it set up correctly to have the tabs inherit methods from the display example, such that they can be invoked as view.tab.display_method_i.call( view.tab ) is that all the variables are part of the view_tab this and the tab index is no longer needed.

function tab( id ) { this.id = id; }

function display( i ) { this.index = i; }
    
tab.prototype.method_1 = function() { };

var view = new display( 0 );
view.tab = Object.create( view );
view.tab = Object.assign( view.tab, new tab( 1 ) );

Solution

  • Can the display.index that contain tab be referenced here?

    No - to illustrate, imagine if the instance was also a property of another object:

    const obj = {};
    function display(i) {
        this.index = i;
        this.tab = new tab(1);
        obj.tab = this.tab;
    }
    

    It's a bit contrived, but it still shows the issue - how would the tab instance know if its method_1 it was called from display or from obj? It can't.

    If you need to do something like this, you should pass the information about the parent down to the tab instance somehow:

    function tab(id, parentDisplay) {
      this.id = id;
      this.parentDisplay = parentDisplay;
    }
    
    function display(i) {
      this.index = i;
      this.tab = new tab(i, this);
    }
    
    tab.prototype.method_1 = function() {
      console.log(this.parentDisplay.index);
    };
    
    var view = new display(0);
    view.tab.method_1();