Three issues:
The run
that A1
puts on instances doesn't return anything, so calling it yields undefined
.
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.
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());