Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to override a function in a Javascript class, and call the base function

Tags:

javascript

Is it possible to override a function in a Javascript class, and call it's base implementation? I've achieved this by using prototypes, but I'm trying to preserve privacy for some of the data.

This is what I have so far, and it doesn't work. I can see why it doesn't work, but I can't see a way to resolve it. I'm beginning to wonder if this is not possible in javascript (without jumping through a lot of hoops).

Also, I need to support IE11, so can't use ES6.

    var NoProto = NoProto || {};

    NoProto.Shape = (function(){
        var thing = function(name){
            var privateData = 'this is a ' + name;

            var self = this;
            this.base = function(){
                return self;
            };

            this.doStuff = function(){
                return privateData;
            };
        };

        return thing;
    })();

    NoProto.Square = (function(){
        var thing = function(colour){
            NoProto.Shape.call(this, "square");

            this.doStuff = function(){
                // this fails (stack overflow)
                // ------> how to call the "base" function: doStuff, and preserve the private data?
                var val = this.base().doStuff();
                return val + ', which is '+ colour;
            };
        };

        thing.prototype = Object.create(NoProto.Shape.prototype);

        return thing;
    })();

Usage:

        var noProtoSqr = new NoProto.Square('blue');
        try {
            alert(noProtoSqr.doStuff()); // ---> Stack Overflow!
        } catch (e){
            console.error('There was an error: ' + e);
        }

For reference, this is how I got it working with prototypes:

    var Proto = Proto || {};

    Proto.Shape = (function(){
        var thing = function(name){
            this._pseudoPrivateData = 'this is a ' + name;
        };

        thing.prototype._pseudoPrivateData = '';
        thing.prototype.doStuff = function(){
            return this._pseudoPrivateData;
        };

        return thing;
    })();

    Proto.Square = (function(){
        var thing = function(colour){
            Proto.Shape.call(this, "square");
            this._colour = colour;
        };

        thing.prototype = Object.create(Proto.Shape.prototype);

        thing.prototype._colour = '';
        thing.prototype.doStuff = function(){
            var val = Proto.Shape.prototype.doStuff.call(this);
            return val + ', which is '+ this._colour;
        };

        return thing;
    })();

Usage:

        var protoSqr = new Proto.Square('blue');
        try {
            alert(protoSqr.doStuff());  // --> "this is a square, which is blue"
        } catch (e){
            console.error('There was an error: ' + e);
        }
like image 690
RikRak Avatar asked Nov 08 '22 02:11

RikRak


1 Answers

When you use

NoProto.Shape.call(this, "square")

this assigns the Shape's doStuff to the current instantiation, if that's what you want. So, now this.doStuff will reference the original doStuff function from NoProto.shape. If you want to overwrite the doStuff function on the current instantiation while being able to call the original doStuff, save a reference to the old doStuff before assigning to this.doStuff:

var thing = function(colour){
  NoProto.Shape.call(this, "square");
  const oldDoStuff = this.doStuff;
  this.doStuff = function(){
    var val = oldDoStuff();
    return val + ', which is '+ colour;
  };
};

Live snippet:

var NoProto = NoProto || {};

NoProto.Shape = (function(){
  var thing = function(name){
    var privateData = 'this is a ' + name;

    var self = this;
    this.base = function(){
      return self;
    };

    this.doStuff = function(){
      return privateData;
    };
  };

  return thing;
})();

NoProto.Square = (function(){
  var thing = function(colour){
    NoProto.Shape.call(this, "square");
    const oldDoStuff = this.doStuff;
    this.doStuff = function(){
      var val = oldDoStuff();
      return val + ', which is '+ colour;
    };
  };

  thing.prototype = Object.create(NoProto.Shape.prototype);

  return thing;
})();

var noProtoSqr = new NoProto.Square('blue');
try {
  console.log(noProtoSqr.doStuff()); // ---> Stack Overflow!
} catch (e){
  console.error('There was an error: ' + e);
}
like image 56
CertainPerformance Avatar answered Nov 14 '22 22:11

CertainPerformance