Search code examples
javascriptprototypemodule-pattern

Adding prototype methods inside module pattern - Error: is not a function


I'm trying to use the module pattern for a simple javascript exercise, but want to also integrate a prototype method. The prototype method is not found when called outside of the module, even after the object has be created. What am I missing? Does using prototype methods inside the module pattern defeat the purpose of module pattern?

var BroChart = (function(){
    "use strict";

    //revealing module pattern
    return {
        Point: Point,
        Series: Series,
        Chart: Chart,
        addPoint: addPoint,
        addPoints: addPoints,
        addSeries: addSeries        
    };

    function Point(x, y){
        this.coordinates = [x, y];
    }

    function Series(label){
      this.pointArray = [];
      this.label = label;
    }

    // method to add single point
    function addPoint(series, point) {

      if (point instanceof Point) {
        series.pointArray.push(point.coordinates);      
      } else {
        console.log('Error: not a valid point');
      }

    }

    // method to add array of points
    function addPoints(series, points) {

      points.forEach(function(point) {
        if (point instanceof Point) {
          series.pointArray.push(point.coordinates);      
        } else {
          console.log('Error: not a valid point');
        }        
      });

    }  


    function Chart(title, data, type){
      this.title = title;
      this.data = data;
      this.type = type;      
      this.printSeries = function() { _printSeries(this); };
    }  

    //prototype method in question
    Chart.prototype.printSeries2 = function() {
        console.log(this.title + ' Chart');
        console.log('Type: ' + this.type);
        console.log('Data Points: ' + this.data.pointArray);
    };

    function addSeries(chart, series) {
      if (series instanceof Series) {
        chart.data.push(series.pointArray);
      } else {
        console.log('Error: not a valid series');
      }
    }

    function _printSeries(chart) {
        console.log(chart.title + ' Chart');
        console.log('Type: ' + chart.type);
        console.log('Data Points: ' + chart.data.pointArray);
    }


})();

    var broSeries = new BroChart.Series('Protein vs. Sick Gainz');
    var firstPoint = new BroChart.Point (343, 21);
    var secondPoint = new BroChart.Point (2, 11);
    var thirdPoint = new BroChart.Point (54, 241);
    var fourthPoint = new BroChart.Point (76, 988);

    BroChart.addPoint(broSeries, firstPoint);
    BroChart.addPoints(broSeries, [secondPoint, thirdPoint, fourthPoint]);

    var Bro = new BroChart.Chart('Protein vs. Sick Gainz', broSeries, 'line');

    Bro.printSeries(Bro);
    //problematic prototype method call
    Bro.printSeries2();

Solution

  • You should create the object at the end of the closure

    var BroChart = (function(){
        "use strict";
    
        function Point(x, y){
            this.coordinates = [x, y];
        }
    
        function Series(label){
          this.pointArray = [];
          this.label = label;
        }
    
        // method to add single point
        function addPoint(series, point) {
    
          if (point instanceof Point) {
            series.pointArray.push(point.coordinates);      
          } else {
            console.log('Error: not a valid point');
          }
    
        }
    
        // method to add array of points
        function addPoints(series, points) {
    
          points.forEach(function(point) {
            if (point instanceof Point) {
              series.pointArray.push(point.coordinates);      
            } else {
              console.log('Error: not a valid point');
            }        
          });
    
        }  
    
    
        function Chart(title, data, type){
          this.title = title;
          this.data = data;
          this.type = type;      
          this.printSeries = function() { _printSeries(this); };
        }  
    
        //prototype method in question
        Chart.prototype.printSeries2 = function() {
            console.log(this.title + ' Chart');
            console.log('Type: ' + this.type);
            console.log('Data Points: ' + this.data.pointArray);
        };
    
        function addSeries(chart, series) {
          if (series instanceof Series) {
            chart.data.push(series.pointArray);
          } else {
            console.log('Error: not a valid series');
          }
        }
    
        function _printSeries(chart) {
            console.log(chart.title + ' Chart');
            console.log('Type: ' + chart.type);
            console.log('Data Points: ' + chart.data.pointArray);
        }
    
        //revealing module pattern
        return {
            Point: Point,
            Series: Series,
            Chart: Chart,
            addPoint: addPoint,
            addPoints: addPoints,
            addSeries: addSeries        
        };
    
    })();
    
        var broSeries = new BroChart.Series('Protein vs. Sick Gainz');
        var firstPoint = new BroChart.Point (343, 21);
        var secondPoint = new BroChart.Point (2, 11);
        var thirdPoint = new BroChart.Point (54, 241);
        var fourthPoint = new BroChart.Point (76, 988);
    
        BroChart.addPoint(broSeries, firstPoint);
        BroChart.addPoints(broSeries, [secondPoint, thirdPoint, fourthPoint]);
    
        var Bro = new BroChart.Chart('Protein vs. Sick Gainz', broSeries, 'line');
    
        Bro.printSeries(Bro);
        //problematic prototype method call
        Bro.printSeries2();
    

    Edit: The explanation is that Chart.prototype.printSeries2 = function(){...} is an statement and is not beeing executed because of the top return.

    See it running here: https://jsfiddle.net/f8ednmw2/