Javascript Inheritance questions

  • Java
  • Thread starter Borg
  • Start date
  • Tags
    Javascript
In summary: Initialization of variables // Code that assembles data based on the variables ); //Code that builds the axes } chart.margin = function (_) { if (!arguments.length) return margin; margin = _; return chart; }; chart.settings = function (_) { if (!arguments.
  • #1
Borg
Science Advisor
Gold Member
2,179
4,234
This is going to be a long post. :wideeyed:

I have been teaching myself Javascript for a project that I'm working on and I am stuck on how to get inheritance working the way that I would like. If this was plain old Java, I would have been done days ago. Some background on the problem - I am building Javascript that uses the d3.js visualization libraries. I am building a tool that allows users to dynamically build various types of visualizations like bar charts, line charts, pie charts, etc. I have this working nicely but have gotten to the point where I'm seeing a lot of duplication that I would like to put into a base class that each of the implementations can use to store common variables and methods. Stripping out the bulk of the implementation details, the working bar chart looks like this:

JavaScript:
function bar_chart() {
    var margin,
        settings,
        width,
        height,
        other variables...;

    function chart(selection) {
        // Initialization of variables

        selection.each(function (data, i) {
            // Code that assembles data based on the variables
         );

        //Code that builds the axes
    }

    chart.margin = function (_) {
        if (!arguments.length) return margin;
        margin = _;
        return chart;
    };

    chart.settings = function (_) {
        if (!arguments.length) return settings;
        settings = _;
        return chart;
    };

    chart.width = function (_) {
        if (!arguments.length) return width;
        width = _;
        return chart;
    };

    chart.height = function (_) {
        if (!arguments.length) return height;
        height = _;
        return chart;
    };

    chart.horizontal = function (_) {
        if (!arguments.length) return horizontal ;
        horizontal = _;
        return chart;
    };

    chart.x = function (_) {
        if (!arguments.length) return xValue;
        xValue = _;
        return chart;
    };

    chart.y = function (_) {
        if (!arguments.length) return yValue;
        yValue = _;
        return chart;
    };

    return chart;
}

In the calling code, this gets run in various ways like this:
JavaScript:
// Setup
var barChart = bar_chart()
.settings(settings)
.y(function (d) { return +d; }); 

// Display
d3.select("#" + svgId)
.datum(barChartData)
.call(barChart);
Now comes the part that I'm stuck on. I would like to have a generic_chart class that each of the different types of charts are based on. Each section in the bar_chart function has code that could be generically used including the variables, things like chart.settings, and parts of the chart(settings) function. I have looked at various tutorials on inheritance and haven't found anything that really does what I would like. This is generally what I'm trying to do:
JavaScript:
// This is an extend method that I found
function extend(base, sub) {
// Avoid instantiating the base class just to setup inheritance // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create // for a polyfill // Also, do a recursive merge of two prototypes, so we don't overwrite // the existing prototype, but still maintain the inheritance chain // Thanks to @ccnokesvar origProto = sub.prototype;
sub.prototype = Object.create(base.prototype);
for (var key in origProto) {
sub.prototype[key] = origProto[key];
}
// Remember the constructor property was set wrong, let's fix itsub.prototype.constructor = sub;
// In ECMAScript5+ (all modern browsers), you can make the constructor property // non-enumerable if you define it like this insteadObject.defineProperty(sub.prototype, 'constructor', {
enumerable: false,
value: sub
});
}

function generic_chart(){
    var margin,
        settings,
        width,
        height;

    chart.margin = function (_) {
        if (!arguments.length) return margin;
        margin = _;
        return this.chart;
    };

    settings = function (_) {
        if (!arguments.length) return settings;
        settings = _;
        return this.chart;
    };

    // Other common chart.<variable> settings
}

generic_chart.prototype = {
 settings: function () {
// Setup to call the settings function above
   }
};

function bar_chart() {
    var barChart-specific variables...;

    function chart(selection) {
        // Initialization of variables from bar_chart and generic_chart functions

        selection.each(function (data, i) {
            // Code that assembles data based on the variables
         );

        //Code that builds the axes
    }

    chart.x = function (_) {
        if (!arguments.length) return xValue;
        xValue = _;
        return chart;
    };

    chart.y = function (_) {
        if (!arguments.length) return yValue;
        yValue = _;
        return chart;
    };

    // Other chart.<variable> settings that are specific to a barChart implementation

    return chart;
}

// Setup the prototype chain
extend(generic_chart, bar_chart);

Then, when I call this:
// Setup
var barChart = bar_chart()
.settings(settings)
.y(function (d) { return +d; });

It would use the settings function in the generic_chart and the y function in the bar_chart. Unfortunately, this just isn't working and every time I get close, something else breaks. Help!
 
Technology news on Phys.org
  • #2
There's a discussion here using a class extends strategy:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

Look further down in the page for the class stuff which seems new to javascript although its been around a while in Java.

In Java I typically make a CommonMethods class and do something like this
Java:
class CommonPlot {

  public method1(...) { ... }     // callable via the instance or in the subclass

  protected method2( ... ) { ... }    // callable inside the subclass but not via the instance

}

class LinePlot extends CommonPlot {  ... }

class BarPlot extends CommonPlot { ... }

...
 
  • Like
Likes Borg
  • #3
jedishrfu said:
There's a discussion here using a class extends strategy:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

Look further down in the page for the class stuff which seems new to javascript although its been around a while in Java.
Thanks. I think that I looked at that page within the last few days but I'll give it some closer scrutiny.
jedishrfu said:
In Java I typically make a CommonMethods class and do something like this
Yes, that's generally what I'm trying to do. If it was Java, I would have finished it in my sleep. :smile:
 
  • #4
Well, still no luck. I've got lots to build and I've spent three full days trying to clean this one small thing. At this point, it isn't worth it anymore unless someone has any better ideas.
 
  • Like
Likes jedishrfu
  • #5
Borg said:
Well, still no luck. I've got lots to build and I've spent three full days trying to clean this one small thing. At this point, it isn't worth it anymore unless someone has any better ideas.
@Borg I am proud of you and your work ethic. Only a
true programmer will spend days trying to get some small nit fixed.
 
  • Like
Likes Borg
  • #6
jedishrfu said:
@Borg I am proud of you and your work ethic. Only a
true programmer will spend days trying to get some small nit fixed.
Thank you for that. I try to do my best but sometimes it's best to try again later.
 
  • #7
There are many different ways to do inheritance in JavaScript. Looking at your code it seems you are using closures to create your objects. Here is an example of how inheritance can be done while sticking with your programming style. This also has the advantage that it behaves similar to Java inheritance and that means Java code would be very easy to translate into JavaScript. btw. just as in Java, this inheritance pattern only allows single inheritance.

JavaScript:
//contructor for generic chart
function Chart(arg1, arg2, ...) {
  //private variables
  var width, height, ...;
  //we use self instead of this
  //no need to bother with the broken behavior of "this" in JS
  var self = {};
  //private methods
  function privateMethod1() {
  }
  function privateMethod2() {
  }
  //public methods
  function method1() {
    ...
    //calling another public method
    //if subclasses were to override method2 it would not
    //affect this at all
    method2();
  }
  function method2() {
    ...
    //calling another public method through self
    //which means if subclasses override it we use the
    //version from the subclass
    self.method1();
  }
  //the instanceof operator doesn't work with this pattern
  //so we define our own
  function instanceOf(s) {
    return s === "Chart";
  }
  //adding public methods to self
  self.method1 = method1;
  self.method2 = method1;
  self.instanceOf = instanceOf;
  return self;
}

function BarChart(arg1, arg2, ...) { //extends Chart
  var privateVar1, privateVar2, ...;
  //extending Superclass
  var self = Chart(arg1, arg2, ...);
  //@Override
  function method1() {
  }
  function method3() {
  }
  var super_instanceOf = self.instanceOf;
  function instanceOf(s) {
    return s === "BarChart" || super_instanceOf(s);
  }
  self.method1 = method1;
  self.method3 = method3;
  self.instanceOf = instanceOf;
  return self;
}
 
Last edited:
  • Like
Likes Borg
  • #8
Thanks. I will give that a try. As you say, there are a lot of different ways to do inheritance. I think that part of the problem that I'm having is trying to mix ideas from various tutorials that don't play well with each other. Your example is a pattern that I haven't seen so I will be interested to see how it works for me.
 
  • #9
Seems to be working with some minor changes to the way that I was previously calling variables and methods. :smile:
 
  • #10
Great, btw. I modified my example and added instanceOf methods since the instanceof operator doesn't work with this pattern. Of course you could also define a global instanceOf function instead.
 
  • Like
Likes Borg

1. What is Javascript Inheritance?

Javascript Inheritance is a way for objects to inherit properties and methods from other objects. It allows for code reuse and promotes a more organized and efficient programming structure.

2. How is Javascript Inheritance different from classical inheritance?

Javascript Inheritance is different from classical inheritance in that it uses a prototype-based approach rather than a class-based approach. In Javascript, objects inherit directly from other objects, rather than from classes.

3. What is the difference between prototypal and prototypical inheritance?

Prototypal inheritance refers to the process of inheriting properties and methods directly from another object. Prototypical inheritance refers to the use of a prototype object to share properties and methods among objects.

4. How do you implement inheritance in Javascript?

Inheritance can be implemented in Javascript by using the "prototype" keyword or the "Object.create()" method. The "prototype" keyword allows for the creation of a prototype object that can be used to share properties and methods among objects. The "Object.create()" method allows for the creation of a new object with a specified prototype object.

5. What are the benefits of using inheritance in Javascript?

Using inheritance in Javascript can help with code organization, promote code reuse, and provide a more efficient way to create and manage objects. Inheritance also allows for the creation of more complex and dynamic objects.

Similar threads

  • Programming and Computer Science
Replies
5
Views
381
  • Programming and Computer Science
Replies
4
Views
746
  • Programming and Computer Science
Replies
23
Views
1K
  • Programming and Computer Science
Replies
32
Views
2K
  • Programming and Computer Science
Replies
17
Views
1K
  • Programming and Computer Science
Replies
9
Views
908
  • Programming and Computer Science
Replies
1
Views
10K
  • Programming and Computer Science
2
Replies
36
Views
2K
  • Programming and Computer Science
Replies
1
Views
1K
  • Programming and Computer Science
Replies
1
Views
281
Back
Top