JavaScript inheritance using prototype - javascript

I've been programming for over 20 years, but have recently turned to JavaScript. Despite spending hours trawling the web, the penny hasn't yet dropped with the prototype inheritance method.
In the simplified code below, I am trying to inherit the 'name' property from the Synthesizer 'class' to the Roland 'class', but the only way I seem to be able to access it is by using 'Synth2.prototype.name' rather than by 'Synth2.name' (which returns undefined). I would like to get the approach working so that I can use 'Synth2.name', as portability is a design requirement.
I would be very grateful for any assistance.
function Synthesizer(name) {
this.name = name;
}
function Roland(name) {
this.prototype = new Synthesizer(name);
}
Synth1 = new Synthesizer("Analogue");
Synth2 = new Roland("Fantom G6");
document.write(Synth1.name + '<br>');
document.write(Synth2.name + '<br>');
Thanks guys! (Now updated with call to super class)...
function Synthesizer(name) {
this.name = name;
this.rendersound = function () {
document.write("applying envelope to " + this.name + "<br>");
}
}
function Roland(name) {
Synthesizer.call(this, name);
this.prototype = Synthesizer;
this.Synthesizer_rendersound = this.rendersound;
this.rendersound = function () {
document.write("applying differential interpolation to " + this.name + "<br>");
this.Synthesizer_rendersound(this);
}
}
Synth1 = new Synthesizer("Analogue");
Synth2 = new Roland("Fantom G6");
document.write(Synth1.name + '<br>');
document.write(Synth2.name + '<br>');
document.write('<br>');
Synth1.rendersound();
document.write('<br>');
Synth2.rendersound();
document.write('<br>');
document.write('Synth1.prototype ' + Synth1.prototype + '<br>');
document.write('Synth2.prototype ' + Synth2.prototype + '<br>');
document.write('<br>');
document.write('Synth1.constructor ' + Synth1.constructor + '<br>');
document.write('Synth2.constructor ' + Synth2.constructor + '<br>');

You can do this by several way.
For example :
var Synthesizer = function(name){
this.name = name;
}
function Roland(name) {
Synthesizer.call(this, name); // you call the constructor of Synthesizer
// and force Synthesizer's this to be Roland's this
}
function clone(obj){
var ret = {};
for(var i in obj){ ret[i] = obj[i]; }
return ret;
}
Roland.prototype = clone(Synthesizer.prototype); // inheritance of public functions
For Function.prototype.call : https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/Call

I believe you have to set the constructor's prototype, like this:
function Synthesizer(name) {
this.name = name;
}
function Roland(name) {
this.name = name;
}
Roland.prototype = new Synthesizer();
Synth1 = new Synthesizer("Analogue");
Synth2 = new Roland("Fantom G6");
document.write(Synth1.name + '<br>');
document.write(Synth2.name + '<br>');

Related

Why does my child class not inherit properties from the parent in Javascript?

I am trying to understand Javascript's prototypical inheritance model but there seems to be something I am missing. I have created the following set of objects:
function Dog() {
this.legs = 4;
this.arms = 0;
}
Dog.prototype.describe = function() {
console.log("Has " + this.legs + " legs and " + this.arms + " arms");
}
function Schnauzer(name) {
Dog.call(this);
this.name = name;
}
Schnauzer.prototype.describe = function() {
console.log(this.name + " is a Schnauzer with a shaggy beard");
Dog.prototype.describe(this);
}
var my_dog = new Schnauzer("Rupert");
my_dog.describe();
My expectation here is that this would output:
Rupert is a Schnauzer with a shaggy beard
Has 4 legs and 0 arms
however this is what i actually get:
Rupert is a Schnauzer with a shaggy beard
Has undefined legs and undefined arms
With
Dog.prototype.describe(this);
you're calling the describe method with a calling context (a this value) of Dog.prototype, and passing the dog instance as the first argument. But describe doesn't accept any arguments, and it tries to take properties from this.
Do Dog.prototype.describe.call(this); instead, to call the method with a this value of the dog instance:
function Dog() {
this.legs = 4;
this.arms = 0;
}
Dog.prototype.describe = function() {
console.log("Has " + this.legs + " legs and " + this.arms + " arms");
}
function Schnauzer(name) {
Dog.call(this);
this.name = name;
}
Schnauzer.prototype.describe = function() {
console.log(this.name + " is a Schnauzer with a shaggy beard");
Dog.prototype.describe.call(this);
}
var my_dog = new Schnauzer("Rupert");
my_dog.describe();
Still, this is kind of ugly, since you have to use .call just to get to a method that, in a normal situation, would be higher up on the prototype chain of the current object. If possible, you might consider re-naming your Schnauzer.prototype.describe method, so it doesn't overshadow the Dog.prototype method:
function Dog() {
this.legs = 4;
this.arms = 0;
}
Dog.prototype.describe = function() {
console.log("Has " + this.legs + " legs and " + this.arms + " arms");
}
function Schnauzer(name) {
Dog.call(this);
this.name = name;
}
Schnauzer.prototype = Object.create(Dog.prototype);
Schnauzer.prototype.describeSchnauzer = function() {
console.log(this.name + " is a Schnauzer with a shaggy beard");
this.describe();
}
var my_dog = new Schnauzer("Rupert");
my_dog.describeSchnauzer();
Or use class syntax and super:
class Dog {
legs = 4;
arms = 0;
describe() {
console.log("Has " + this.legs + " legs and " + this.arms + " arms");
}
}
class Schnauzer extends Dog {
constructor(name) {
super();
this.name = name;
}
describe() {
console.log(this.name + " is a Schnauzer with a shaggy beard");
super.describe();
}
}
var my_dog = new Schnauzer("Rupert");
my_dog.describe();

How can i get rid of putting "new" before a function

I was wondering how can I make it posible to get rid of putting "new" before a function, for example:
new functionToDo("thingsToDo").iGotYouBruh("Halo Humans");
is there a posible way of doing this without the "new"?
here is the code I'm trying to use without the "new":
function local (title) {
var storeTitle = title;
this.addL = function(lString) {
var storeText = lString;
localStorage.setItem(storeTitle, storeText);
console.info("Locally stored " + storeTitle.toUpperCase() + " with " + storeText.substring(0, 10) + "... As text.");
};
this.removeL = function() {
localStorage.removeItem(storeTitle);
console.info("Locally removed " + storeTitle + ".");
};
this.getL = function () {
localStorage.getItem(storeTitle);
console.info("Locally got string of " + storeTitle + ": " + localStorage.getItem(storeTitle));
};
};
and here's what I would have to do to invoke the function:
new local("storedElement").getL();
This is possible by checking whether this is an instance of the function itself and returning a new instance otherwise:
function local (title) {
if (!(this instanceof local)) {
return new local(title);
}
var storeTitle = title;
this.addL = function(lString) {
var storeText = lString;
localStorage.setItem(storeTitle, storeText);
console.info("Locally stored " + storeTitle.toUpperCase() + " with " + storeText.substring(0, 10) + "... As text.");
};
this.removeL = function() {
localStorage.removeItem(storeTitle);
console.info("Locally removed " + storeTitle + ".");
};
this.getL = function () {
localStorage.getItem(storeTitle);
console.info("Locally got string of " + storeTitle + ": " + localStorage.getItem(storeTitle));
};
};
You could use JavaScript closures. In particular look at the "Using Closures for the Module Pattern" section of this webpage for a full description. The idea is to have the function return an literal with all the required methods. Any functions or variables that you want to be kept private are just local variables for the function.

javascript: object inheritance is not able understand

I am working inheritance in JavaScript, here, have created two objects. on the below code, when try to alert as alert(newOnj.whatAreYou());, now, it is working fine. But, when i try to alert alert(newOnj.whatAreYounow());, now, am getting error as 'newOnj.whatAreYounow is not a function'. Actually, have inherited parent class to child class as subGadget.prototype = new Gadget();. what is the thing that i haven't understood here? please
function Gadget() {
this.name = "Alex";
this.color = "red";
this.whatAreYou = function(){
return 'I am a ' + this.color + ' ' + this.name;
}
}
function subGadget() {
this.whatAreYounow = function(){
return 'Now, I am a ' + this.color + ' ' + this.name;
}
}
subGadget.prototype = new Gadget();
var newOnj = new Gadget();
alert(newOnj.whatAreYounow());
You need to write -
var newOnj = new subGadget();

Javascript OOP - inheritance, prototyping, callback function

I'm trying to use OOP in Javascript with inheritance, prototyping and callback functions. Would you please have a look at my JSfiddel http://jsfiddle.net/Charissima/5g6GV/.
The first problem is solved already in Javascript OOP - inheritance and prototyping, but unfortunately the callback functions don't work any more.
function Car () {
this.totalDistance = 0;
};
Car.prototype.putTotalDistance = function(distance) {
this.totalDistance = distance;
};
Car.prototype.getTotalDistance = function() {
return this.totalDistance;
};
Car.prototype.drive = function(distance) {
this.totalDistance += distance;
return this.totalDistance;
};
function RaceCar () {};
RaceCar.prototype = new Car();
RaceCar.prototype.parent = Car.prototype;
RaceCar.prototype.drive = function(distance) {
return this.parent.drive.call(this, (distance * 2));
};
var myText;
car = new Car;
raceCar = new RaceCar;
car.putTotalDistance(200);
myText = 'car totalDistance = ' + car.drive(10) + ' - ok<br>';
raceCar.putTotalDistance(200);
myText += 'raceCar totalDistance before drive = ' + raceCar.getTotalDistance() + ' - ok<br>';
myText += 'raceCar totalDistance after drive = ' + raceCar.drive(10) + ' - ok<br><br>';
car.putTotalDistance(0);
raceCar.putTotalDistance(100);
var drivingFunctions = [car.drive, raceCar.drive];
myText += drivingFunctions[0](10) + '<br>';
try {
myText += drivingFunctions[1](100) + '<br>';
}
catch(err) {
myText += err + + '<br>'
}
document.body.innerHTML = myText;
You've put the two functions in an array, so when called, this get changed.
You could use function bind :
var drivingFunctions = [car.drive.bind(car), raceCar.drive.bind(raceCar)];
Here is an example to help you understand:
function Man(name){
this.name = name;
this.getName = function(){
return this.name;
};
}
var man = new Man('toto');
var a = [man.getName];
console.log(a[0]());//undefined
a.name = 'titi';
console.log(a[0]());//titi, because this refers to the array.

How to Use Inheritance in JavaScript with Constructor Methods Returning Object Literals with Private Properties?

var Animal = function(config) {
config = config || {};
var name = config.name,
numLegs = config.numLegs,
weight = config.weight,
speed = config.speed,
sound = config.sound
return {
getName: function () {
return name;
},
getNumLegs: function () {
return numLegs;
},
getWeight: function () {
return weight;
},
getSpeed: function () {
return speed;
},
getSound: function () {
return sound;
},
run: function(distance, unit) {
unit = unit || 'miles';
return 'The ' + name + ' ran ' + distance + ' ' + unit;
},
speak: function() {
return 'The ' + name + ' says "' + sound + '"';
}
}
};
function DragonFly(config) {
var me = {},
numWings = config.numWings;
me.prototype = new Animal(config);
me.getNumWings = function() {
return numWings;
};
me.fly = function(distance, unit) {
unit = unit || 'miles';
return 'The ' + me.name + ' flew ' + distance + ' ' + unit;
}
return me;
}
var dragonFly = new DragonFly({
numWings: 2,
name: 'DragonFly',
numLegs: 6
});
Okay, coming from a PHP background, I don't understand inheritance in JavaScript one bit and I'd like some help.
Basically, here's what I'd like to be able to do with an instance of the dragonFly object:
dragonFly.getName(); // 'DragonFly'
dragonFly.fly(1, 'mile'); // 'The dragonfly flew 1 mile';
dragonFly.run(1, 'yard'); // 'The dragonfly ran 1 yard';
I'd also like to know how to override methods and call the parent of those overridden methods. What is wrong with my approach? All the examples above return undefined or throw an error. The main reason I went with the object-literal style is so I could make properties private.
the "fastest" way :
var Animal = function(config) {
config = config || {};
var name = config.name,
numLegs = config.numLegs,
weight = config.weight,
speed = config.speed,
sound = config.sound
return {
getName: function () {
return name;
},
getNumLegs: function () {
return numLegs;
},
getWeight: function () {
return weight;
},
getSpeed: function () {
return speed;
},
getSound: function () {
return sound;
},
run: function(distance, unit) {
unit = unit || 'miles';
return 'The ' + name + ' ran ' + distance + ' ' + unit;
},
speak: function() {
return 'The ' + name + ' says "' + sound + '"';
}
}
};
function DragonFly(config) {
var me = new Animal(config);
var numWings = config.numWings;
me.getNumWings = function() {
return numWings;
};
me.fly = function(distance, unit) {
unit = unit || 'miles';
return 'The ' + me.name + ' flew ' + distance + ' ' + unit;
}
return me;
}
var dragonFly = new DragonFly({
numWings: 2,
name: 'DragonFly',
numLegs: 6
});
You are mixing 2 kind of "inheritance" in your script , the "classical" inheritance and the prototypal inheritance , you cant do that unless you want to be in serious trouble. both work , both have their pros and cons. Stick to the "classical" inheritance , or object augmentation since you began with it.
An object literal doesnt have a prototype , functions have prototypes. That's why in my opinion js isnt "really" object oriented , but it can mimic object oriented langages
A good exercice now would be to try using functions and prototypes , though i'm not sure you could create private fields with that.
Edit : the me.name should be me.getName() since name is "private". i think.

Categories