简体   繁体   中英

How to call a constructor method of Parent class from child prototype in javascript?

Below is the code snippet, where I have defined 'run' method in the constructor unlike 'eat' method which is defined in the prototype. How can i access this 'run' method from B1's prototype which is inherited from A1. My intension is to override 'run' method in B1 where I can use existing 'run' method of A1. Is there any way to achieve it?

 function A1() { this.run = function() { return 'A1 runs'; } }; A1.prototype.eat = function() { return 'A1 eats'; }; function B1() { A1.call(this); }; B1.prototype = Object.create(A1.prototype); //new A1(); B1.prototype.eat = function() { return A1.prototype.eat.call(this) + ',B1 also eats'; } B1.prototype.run = function() { var parentRun = this.constructor.run(); var result = parentRun + ",B1 also runs"; return result; }; var b1 = new B1(); b1.eat(); // It will give 'A1 eats, B1 also eats', which is fine b1.run(); // It will give 'A1 runs', where I want 'A1 runs, B1 also runs'.

Edit 1: I have updated the code snippet, i have removed the console.log and returned the string from each method.

Initially i did not put my research about this. A few people have mentioned it duplicate of this , I had gone through the same link but my question is totally different. I know how to call a method of Parent class's prototype which I have done for "eat".

My query is simple,
is there any way to access the methods of Parent class's constructor ('run' method), not the method of prototype ('eat' method)?

Three issues:

  1. The run that A1 puts on instances doesn't return anything, so calling it yields undefined .

  2. A1 puts run on the instance , which means that in your b1 instance, B1.prototype.run has been obscured by the run that A1 assigned directly to the instance.

  3. this.constructor.run() isn't how you would call the A1 version.

If you put run on A1.prototype , you can do it:

function A1() {
}
A1.prototype.eat = function() {
    console.log('A1 eats');
};
A1.prototype.run = function() {
    return 'A1 runs';
};

function B1() {
    A1.call(this);
}
B1.prototype = Object.create(A1.prototype);

B1.prototype.run = function() {
    return A1.prototype.run.call(this) + ",B1 also runs";
};
var b1 = new B1();
console.log(b1.run());

That's ugly, which is why I wrote a script to automate supercalls back in the day , but it's how you do it when working at this level.

These days, though, you'd use ES2015's class syntax and super instead, transpiling with Babel or Traceur or similar if necessary to support obsolete JavaScript engines:

 class A1 { eat() { console.log("A1 eats"); } run() { return "A1 runs"; } } class B1 extends A1 { run() { return super.run() + ",B1 also runs"; } } var b1 = new B1(); console.log(b1.run());


Re your edit saying you don't want run to be on the prototype, that it has to be assigned by A1 like this:

function A1() {
    this.run = function() {
        return 'A1 runs';
    };
}

That's a bit more of a hassle, but you can still do it. For the reason I stated above, setting run on the instance will obscure the B1.prototype.run that your instance would normally use. So to use that, but also call A1 's non-prototype run , you have to replace it on the instance.

For that reason, it would make sense to define B1 's run in B1 rathr than on B1.prototype , just like A1 defines it in A1 , not on A1.prototype :

function B1() {
    var A1run;
    A1.call(this);
    A1run = this.run;
    this.run = function() {
        return A1run.call(this) + ",B1 also runs";
    };
}

Live example:

 function A1() { this.run = function() { return 'A1 runs'; }; } A1.prototype.eat = function() { console.log('A1 eats'); }; function B1() { var A1run; A1.call(this); A1run = this.run; this.run = function() { return A1run.call(this) + ",B1 also runs"; }; } B1.prototype = Object.create(A1.prototype); var b1 = new B1(); console.log(b1.run());

But if you really, really want it to be (at least partially) on B1.prototype :

function B1() {
    var A1run;
    A1.call(this);
    A1run = this.run;
    this.run = function() {
      return A1run.call(this) + B1.prototype.run.call(this);
    };
}
// ...
B1.prototype.run = function() {
    return ",B1 also runs";
};

Live example:

 function A1() { this.run = function() { return 'A1 runs'; }; } A1.prototype.eat = function() { console.log('A1 eats'); }; function B1() { var A1run; A1.call(this); A1run = this.run; this.run = function() { return A1run.call(this) + B1.prototype.run.call(this); }; } B1.prototype = Object.create(A1.prototype); B1.prototype.run = function() { return ",B1 also runs"; }; var b1 = new B1(); console.log(b1.run());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM