javascript inheritance, constructor called twice - javascript

function Parent (arg1, arg2) {
alert(arg1);
this.member1 = arg1;
this.member2 = arg2;
};
Parent.prototype.update = function () {
// parent method update
};
function Child (arg1, arg2, arg3) {
Parent.call(this, arg1, arg2);
this.member3 = arg3;
};
Child.prototype = new Parent;
Child.prototype.update = function () {
// overwritten method update
};
function init () {
var childObject = new Child(false, false, false);
childObject.update();
}
The result are two alerts with
undefined
false
Why does the alert occurs two times? I already searched, but haven't found anything yet + don't know what to search for.
The result should be one alert with 'false', or am i wrong?
Thx alot!

By using the constructor of Parent to create the prototype for Child, the constructor is being called which is your first alert of undefined.
In order to create a prototype that still uses the same prototype chain, but doesn't call the parent constructor as the prototype is created, you need to add another step in between.
Child.prototype = (function() {
var Base = function() {};
Base.prototype = Parent.prototype;
return new Base();
}());
This will create an anonymous function (called Base) that has the prototype set to be the prototype of the Parent class, the Child prototype is then assigned to a new Base which will preserve the inheritance, but doesn't call the constructor of Parent as the prototype chain is created.

There is one alert when you create a new object of Parent Child.prototype = new Parent; and one when you create new object of child, var childObject = new Child(false, false, false);

Related

Different ways of creating javascript prototype inheritance chain

function Parent(parentName){
this.name = parentName;
}
Parent.prototype.printName = function(){
console.log(this.name);
}
var p = new Parent("Parent");
console.log(p);
function Child(parentName, childName){
Parent.call(this, parentName);
this.name = childName;
}
1. Child.prototype = Object.create(Parent.prototype);
2. Child.prototype = Parent.prototype;
var c = new Child("Parent","Child");
console.log(c);
Can someone tell me the difference between the above statements 1 & 2. In either way child object is able to call c.printName();
There is a big difference between the 2,
one of the most confusing parts with prototypes is the fact you have prototype and proto.
Protoype is a special property of function objects, whenever you invoked a constructor function with the new keyword, the instance proto, will be the constructor prototype.
Object.create is method that allows you to create a new object, and specify it proto.
So when assigning your Child class prototype via method 1, you are giving your child class a completely new prototype object, that will inherit via prototype inheritance through the proto link, the methods of parent.
This is the preferable option, as you can make modifications to the child prototype without affecting the parent prototype, since it a different object.
On the other hand on option 2
You are assigning the same prototype for both classes, they both reference the same object, thus changes to child prototype will affect parent prototype, which is usually not the desired case, nor a good practice.
Example of method 1:
Child.prototype = Object.create(Parent.prototype);
function Parent(){
this.x = 0;
}
Parent.prototype.add = function(n){
this.x+= n;
return this.x;
};
var parentInstance = new Parent();
console.log('new Parent instance');
console.log('parentInstance.add(1): ' + parentInstance.add(1));
console.log('now letss add child, which will always add 10, to the add value');
function Child(){
Parent.call(this);
}
console.log('setting child prototype via method 1');
console.log('Child.prototype = Object.create(Parent.prototype);');
Child.prototype = Object.create(Parent.prototype);
console.log('overriding child add function, to always add 10 to given n');
Child.prototype.add = function(n){
this.x+= n + 10;
return this.x;
}
var childInstance = new Child();
console.log('new child instance');
console.log('childInstance.add(1): ' + childInstance.add(1));
console.log('yay child is working');
console.log('now lets add again to our parent instance');
console.log('parentInstance.add(1): ' + parentInstance.add(1));
console.log('yay parent is still working');
Example of method 2:
Child.prototype = Parent.prototype;
function Parent(){
this.x = 0;
}
Parent.prototype.add = function(n){
this.x+= n;
return this.x;
};
var parentInstance = new Parent();
console.log('new Parent instance');
console.log('parentInstance.add(1): ' + parentInstance.add(1));
console.log('now letss add child, which will always add 10, to the add value');
function Child(){
Parent.call(this);
}
console.log('setting child prototype via method 2');
console.log('Child.prototype = Parent.prototype;');
Child.prototype = Parent.prototype;
console.log('overriding child add function, to always add 10 to given n');
Child.prototype.add = function(n){
this.x+= n + 10;
return this.x;
}
var childInstance = new Child();
console.log('new child instance');
console.log('childInstance.add(1): ' + childInstance.add(1));
console.log('yay child is working');
console.log('now lets add again to our parent instance');
console.log('parentInstance.add(1): ' + parentInstance.add(1));
console.log('oops we broke parent');
the difference between 1 and 2 is that
1st one you are creating a new object with the specified prototype object and properties, not shared with a parent
what Object.create(Parent.prototype) does is it returns a new object with the prototypes of the parent, but the 2nd one you are just referencing (pointing) the child prototype to the parent prototype, so if you add a property to the child prototype say,
Child.prototype.age = function(){
console.log("parent can access this method");
}
p.age();
the parent can access this method gets printed, for classical inheritance you would want to use the first method but there are some use cases for the second method
just to expand on this post, in my opinion the best way to do inheritance is to do
// parent object
var Parent = {
firstname: "john",
getFirstName : function () {
console.log(this.firstname);
}
};
// create a child object with all the properties and methods of Parent
var child = Object.create(Parent);
// add or modify child properties
child.lastname = "doe";
child.getLastName = function () {
console.log(this.lastname);
};
// create instances of child object
baby1 = Object.create(child);
baby1.firstname = "alice";
baby1.getFirstName();
baby1.getLastName();
// to see the prototype chain
console.log("baby1 properties: ", baby1);
console.log("baby1 parent properties: ", baby1.__proto__);
console.log("baby1 grandpa properties: ", baby1.__proto__.__proto__);
very simple and no use of call or manual prototype management

For JavaScript prototypal inheritance, why can't a parent object be created and saved in a child's constructor?

In this JavaScript code, when the instantiation of new child causes its constructor to execute, the create method does not seem to creating the parent object. The child does not seem to inherit the parent's member function m.
function parent() {
parent.prototype.a =2;
parent.prototype.m = function() {
return this.a++;
}
}
function child() {
child.prototype = Object.create(parent.prototype);
child.prototype.constructor = parent;
parent.call(this);
}
var c = new child();
alert(child.prototype.m()); // 2
alert(child.prototype.m()); // 3
alert(c.m()); // FAILS!!!
Your prototype methods and inheritance should be defined outside of your functions...
function parent() {
}
parent.prototype.a =2;
parent.prototype.m = function() {
return this.a++;
}
function child() {
parent.call(this);
}
child.prototype = Object.create(parent.prototype);
var c = new child();
alert(child.prototype.m()); // 2
alert(child.prototype.m()); // 3
alert(c.m()); // 4
Here is basically what happens when you run new child:
var obj = Object.create(child.prototype);
child.call(obj);
return obj;
Inlining your constructor would look like:
var obj = Object.create(child.prototype);
// inline
child.prototype = Object.create(parent.prototype);
child.prototype.constructor = parent;
parent.prototype.a =2;
parent.prototype.m = function() {
return this.a++;
}
// end inline
return obj;
Do you notice that nothing in the constructor modifies obj in any way? While you modifying child.prototype and parent.prototype, this has no effect on obj, since created a new object with child.prototype = Object.create(parent.prototype), where obj inherits from the old child.protoype object.
Here is a simplified example of what you are doing:
var proto = {};
var obj = Object.create(proto);
proto = {};
proto.m = function() {};
It should be pretty clear that assigning to proto.m has no effect on obj, since we assigned a new object o proto beforehand.
There have been many question about OOP in JS on Stack Overflow already, you can easily search for them. I also recommend to read the MDN article about OOP in JS and Benefits of using `Object.create` for inheritance
It looks like you are misunderstanding how to setup custom objects in JavaScript. Normally you would add your methods to the prototype outside the constructor, doing it inside will reset the properties every time the constructor is called.
function parent() {
}
parent.prototype.a = 2;
parent.prototype.m = function() {
return this.a++;
}
function child() {
parent.call(this);
}
child.prototype = Object.create(parent.prototype);
child.prototype.constructor = parent;
var c = new child();
alert(child.prototype.m()); // 2
alert(child.prototype.m()); // 3
alert(c.m()); // 4
In this case, it is failing because you create the new prototype for the child.
Object.create(parent.prototype);
Before you set your m method it in the parent constructor.

why prototype javascript not works in that case

My case(why "test1" not appear in alert window):
var Parent=function(){
this.test1= function(){
alert("test1");
}
}
var Child=function(){
this.prototype=new Parent();
}
var test=new Child();
test.test1();
http://jsfiddle.net/c3sUM/2/ (same code online to try)
​
Thanks
The problem is you didn't assign the Child's prototype but instead, made a property prototype in the instance of Child which points to an instance of Parent .
instead, do this:
var Child = function(){}; // create constructor
Child.prototype = new Parent(); // assign instance of parent to constructor's
// prototype
A similar answer might help
Your code would be much clearer using function declarations:
// Parent constructor
function Parent() {}
// Methods of Parent.prototype are inherited by
// instances of parent
Parent.prototype.test1 = function() {
alert('test 1');
}
// Child constructor
function Child(){}
// Make Child.prototype an instance of Parent so
// instances inherit from Child and Parent
Child.prototype = new Parent();
// Instance inherits from Child (and hence Parent);
var child = new Child();
child.test1(); // 'test 1'
The only reason to use function expressions over declarations in this case is if you want to dynamically create the constructors based on some other logic.

Javavscript change sub-class property on instantiation

if I have
myClass.prototype.subClass=
{
foo:false
}
when I create a new instance on an object how can I set foo to a different value each time, so how do I refer to that sub-class here
var newObj = new myclass();
Objects and arrays are not something which should be added to the prototype unless you want to share them with all instances.
As soon as you want properties of these objects to be different for each instances, you have to assign the object in the constructor (or in any other function) to the specific instance:
this.subClass = {
foo: true
// potentially other properties
};
That said, there might be cases were having a "default" object in the prototype might be reasonable, but you should not write to it.
Assigning the object in the constructor instead does not duplicate code and allows you to change it for each instance individually.
Update:
If you don't want to change the original constructor, you can either just add a new function to the prototype and call it whenever you instantiate an object:
MyClass.prototype.init = function() {
this.subClass = {
//...
};
};
and
var obj = new MyClass();
obj.init();
Or you really create a new constructor function:
function MySubClass() {
MyClass.apply(this, arguments);
// now create that object for each instance
this.subClass = {
foo: someValue
};
}
inherits(MySubClass, MyClass);
where inherits is defined as:
function inherits(Child, Parent) {
var Tmp_ = function() {};
Tmp_.prototype = Parent.prototype;
Child.prototype = new Tmp_();
Child.prototype.constructor = Child;
}
Then you will use MySubClass instead of MyClass to create the instances.
I think you missunderstand how prototype inheritence works because this question is a bit odd. But you should be able to access the foo property like any other:
newObj.subClass.foo = newValue

Javascript instantiating child class with parent properties

I am new to oop in Javascript and just need to get to grips with this.
If I have a class with properties
function myClass(){
this.foo=null;
}
I then use inheritance to create a child class
myChild.prototype = new myClass();
function myChild(){
alert(this.foo);
}
How do I set the property of foo when instantiating the child class e.g I want to alert 'bar'. I don't want to simply pass 'bar' to myChild as I have a list of properties to set that are relevant to a method in myClass and not myChild.
var newChild = new myChild();
You can actually find the answer to this question also in my answer to previous question and it is similar to inheritance in other languages.
If you extend a class, the constructor function of the child class has to accept its own arguments and the one for the parent class. So assuming you have:
function Parent(a) {
this.foo = a;
};
// and
function Child(b, a) {
Parent.call(this, a); // executes the parent constructor for this instance
this.bar = b;
alert(this.foo);
};
inherits(Parent, Child);
(the implementation of inherits can be found in this answer).
Inside Child you have to call the construtor of the parent class and pass the parameters, similar how you do it in Java or Python.
If you have many parameters, then you can make use of the arguments object, to make things a bit easier:
function Parent(a, b, c, d) {...};
function Child(e, f) {
// c and d are parameters for `Child`
// arguments[0] == e
// arguments[1] == f
// all other arguments are passed to Parent, the following
// creates a sub array arguments[2..n]
Parent.apply(this, [].slice.call(arguments, 2);
/...
}
// later
var child = new Child(e, f, a, b, c, d);
In general, myChild.prototype = new myClass(); is not a good inheritance pattern as most of the time, classes expect some arguments. This won't execute the parent constructor for each instance but only once for all instances.
You could just set the property in the child's constructor like so:
myChild.prototype = new myClass();
function myChild(){
this.foo = "bar";
}
Is that what you want?
Or if you want to be flexible about what foo contains in each instance you could just set it right after instantiation of the child class:
var child = new myChild();
child.foo = "bar";
Parameterize your construction method.
function myClass(foo){
this.foo=foo;
}
myChild.prototype = new myClass('bar');
function myChild(){
alert(this.foo);
}
var newChild = new myChild();
or:
function myClass(){
this.foo=null;
}
myChild.prototype = new myClass();
myChild.prototype.foo = 'bar';
function myChild(){
alert(this.foo);
}
var newChild = new myChild();

Categories