how to extend javascript classes - javascript

Why Child class doesn't have echo() method?
Parent = function(){
this.name = 'abc';
}
Parent.prototype.echo = function(){
alert(this.name);
}
Child = function(){
$.extend(this, Parent);
}
var x = new Child();
x.echo();
What should I do to inherit from parent class in Javascript?

You need to set the prototype of Child to Parent.
function Parent() {
this.name = 'abc';
}
Parent.prototype.echo = function () {
alert(this.name);
}
function Child() {
}
Child.prototype = new Parent()
var x = new Child();
x.echo();

I'm assuming you use jQuery. The jQuery extend system uses objects, not 'classes', see: http://api.jquery.com/jQuery.extend/

There are no 'classes' in javascript, only objects and prototypal inheritance
Parent, Child are not classes, they are functions(as well as objects)
Within Child, 'this' refers to the global object('window' for browsers)
use Child.prototype = new Parent()

Related

How prototype inheritance can affect method overriding in JavaScript?

Here’s the code,
function extend(child, parent) {
child.prototype = Object.create(parent.prototype);
child.prototype.constructor = child
}
//Super Class
var Mobile = function() {}
//Prototype Method
Mobile.prototype.show = function() {
return "Super Class Method";
}
//Sub class
var Samsung = function() {}
extend(Samsung, Mobile);
Samsung.prototype.show = function() {
return "Sub Class Method";
}
var sam = new Samsung();
document.write(sam.show()); //displays "Sub Class Method"
function extend(child, parent) {
child.prototype = Object.create(parent.prototype);
child.prototype.constructor = child
}
//Super Class
var Mobile = function() {}
//Prototype Method
Mobile.prototype.show = function() {
return "Super Class Method";
}
//Sub class
var Samsung = function() {}
Samsung.prototype.show = function() {
return "Sub Class Method";
}
extend(Samsung, Mobile);
var sam = new Samsung();
document.write(sam.show()); //displays "Super Class Method"
When I extend Samsung.prototype with Mobile.prototype before initializing the prototype method show() for Samsung, I get to see the show() method of Samsung.prototype, But writing it after initialization provides me with show() method of Mobile.prototype. Could someone please explain why is this happening as I'm new to JavaScript?
Note about the first code snippet:
This pattern is called behavior delegation, the parent and child prototypes are linked together using your extend function, they're not copy of each others they are the same, but when you assign a new value to a property that already exist in the prototype chain, you shadow it and the new value will be used whenever you ask for it and not the value from the parent prototype.
In the second code snippet after creating a show method for the child, you override the whole prototype object all over again, and it's a normal result because you manually made its prototype to point to the new parent prototype.

Call parent prototype from child prototype

My parent class is
function Parent() {}
Parent.prototype.get = function() {}
Parent.prototype.start= function() { this._start() }
My child is
function Child(){ Parent.call(this, arguments) }
Child.prototype._start = function(){ this.get() /* error here - this.get is not a function*/ }
util.inherits(Child, Parent);
When I do
new Child().start()
I got an error this.get is not a function. How can I call parent prototype function? Thanks.
As the use of util.inherits is discouraged, you should use extends for classes, but you seem to have just regular functions, which means you can set the prototype of the child to the same as the parent before starting to extend it further
function Parent() {}
Parent.prototype.get = function() {
console.log('works fine');
}
Parent.prototype.start = function() {
this._start();
}
function Child() {
Parent.call(this, arguments);
}
Child.prototype = Parent.prototype;
Child.prototype._start = function() {
this.get();
}
var instance = new Child();
instance.start();
Note that Parent and Child now have the same prototype, so by changing one, you'd be changing the other as well.
If for some reason you have to avoid that, using Object.create (or assign) would do that
Child.prototype = Object.create(Parent.prototype);

Prototypes and property inheritence in JavaScript

I am struggling accessing a property that is set on a child object and accessing it via method on its prototype.
var Parent = function () {
this.getColor = function () {
return this.color;
};
};
var Child = function () {
this.color = red;
};
Child.prototype = new Parent;
var Test = new Child();
console.log(Test.getColor());
=> undefined
Any and all assistance is appreciated.
Here's how I'd do it
function Parent(color) {
function getColor() {
return color;
}
// export public functions
this.getColor = getColor;
}
Now for the Child
function Child(color) {
Parent.call(this, color);
}
Child.prototype = Object.create(Parent.prototype, {
constructor: {value: Child}
});
Let's see it work
var c = new Child("red");
c.getColor(); // "red";
Explanation:
The important bits of the Child constructor
Make sure to call the Parent constructor with the context of the Child instance (this)
Parent.call(this, color);
Setup the Child.prototype based off of the Parent.prototype
Child.prototype = Object.create(Parent.prototype, {
constructor: {value: Child}
});
You can see the node.js implementation of util.inherits uses a similar method.
This somewhat complicated line does two things for you. 1) It avoids invoking the parent constructor unnecessarily, 2) It sets the constructor property properly.
var c = new Child("red");
c instanceof Child; // true
c instanceof Parent; // true
c.constructor.name; // "Child"
But using your code, you would see
var c = new Child("red");
c instanceof Child; // true
c instanceof Parent; // true
c.constructor.name; // "Parent"
This may or may not be a concern for you, but depending on how you want to use your parent/child objects, it may be hard to programmatically differentiate which objects are from the Parent constructor and which ones are from the Child constructor.
Ok, let's see another way to do it by assigning the color property on the object itself
function Parent(color) {
this.color = color;
}
We'll add the getColor method directly to the Parent.prototype
Parent.prototype.getColor = function getColor() {
return this.color;
};
The Child constructor will stay the same. Keep in mind we'll use the same inheritance pattern we used above
function Child(color) {
Parent.call(this, color);
}
Child.prototype = Object.create(Parent.prototype, {
constructor: {value: Child}
});
Lastly, let's get the color using our getColor method
var c = new Child("red");
c.getColor(); // "red"
Or you could access the property on the object directly
c.color; // "red"

Accessing parent property in javascript

I'm new to JS and have a question about inheritance. How are inherited properties accessed through the child class?
Lets say I have the following classes:
function ParentClass(parentArg) {
this.parentProperty = parentArg;
}
function ChildClass(childArg1, childArg2) {
this.prototype = new ParentClass(childArg1);
this.childProperty = childArg2;
}
And at some point an object is created of ChildClass, like so:
var foo = new ChildClass('value 1', 'value 2');
Then how can a parent property be accessed from the instance of the child? The following returns 'undefined'.
var parentValue = foo.parentProperty;
Much appreciated.
Cheers
If you want to initialize the parentProperty, you have to do it like this
function ParentClass(parentArg) {
this.parentProperty = parentArg;
}
function ChildClass(childArg1, childArg2) {
ParentClass.call(this, childArg1);
this.childProperty = childArg2;
}
And to actually inherit Parent't methods, you might want to do
ChildClass.prototype = Object.create(ParentClass.prototype);
After making these changes,
var foo = new ChildClass('value 1', 'value 2');
console.log(foo);
# { parentProperty: 'value 1', childProperty: 'value 2' }
foo.prototype.parentProperty If you want to get value 1 back
The problem is because you can't assign to a prototype property before the object definition is declared:
Doesn't work:
function Parent() {
this.parentProperty = "test";
}
function Child() {
// This doesn't work because the prototype is set inside of the definition
this.prototype = new Parent();
}
var child = new Child();
alert(child.parentProperty);
Works
function Parent() {
this.parentProperty = "test";
}
function Child() {
// Define prototype outside of function constructor
}
Child.prototype = new Parent();
var child = new Child();
alert(child.parentProperty);
Also notice that in the second example we assign to Child.prototype and not new Child().prototype
For ES6, you use extends, eg
class A { prop = "prop" }
class B extends A{}
new B();

Javascript: How to extend class properly

Searching over the internet I'm always bumping on this approach of Javascript classes extension
function extend(Child, Parent) {
var F = function() { }
F.prototype = Parent.prototype
Child.prototype = new F()
Child.prototype.constructor = Child
Child.superclass = Parent.prototype
}
But how is that different from this one?
function extend(Child, Parent) {
var p = new Parent()
Child.prototype = p
Child.prototype.constructor = Child
Child.superclass = p
}
This last one also works perfect. So why should I use this extra var F = function() { } move then?
Invoking the original constructor directly can have undesirable side effects, like not working properly if certain expected arguments are not passed.
That's why they use a "proxy" function, which lets you get a new object that inherits from Parent() without actually invoking Parent().
Here's a simple example:
function Person(name, age) {
if (name === undefined)
throw "A name is required";
this.name = name + "";
this.age = age;
}
If Person is the parent, it'll throw an error because there was no name passed.
The first example is (as cookie monster mentioned in the comment) a shim for the following piece of code which might be easier to understand.:
function extend(Child, Parent) {
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
Child.superclass = Parent.prototype;
}
Basically, this implementation makes the object that all Child instances inherit from (Child.prototype) inherit from the object that all Parent instances inherit from (Parent.prototype). Intuitively this is the most accurate representation of class inheritance JavaScript provides.
The second implementation of extends is flawed, because all Child instances will inherit from a specific Parent instance. Should there be significant differences between Parent instances (due to the parameters passed to the constructor for example), the Child instances can not accurate represent that, because they all inherit from a Parent instance created by calling the Parent constructor with no arguments.
Here is an example of what the first implementation can do and the second one can not:
function Parent(name, age) {
this.name = name;
this.age = age;
}
Parent.prototype.greet = function() { return 'I am parent ' + this.name; }
function Child(name){
Parent.call(this, name, 20); // notice the call to the superclass
}
extend(Child, Parent);
Parent.prototype.greet = function() { return 'I am child ' + this.name + ' and i\'m ' + this.age; }
var c = new Child('Tom');
console.log(c.greet()); // I am child Tom and i'm 20
As a sidenote, in the Child constructor i have called the Parent constructor. This is actually quite common when dealing with classical inheritance, so that's another point for the first implementation. It isn't actually required, the Child constructor can safely ignore calling the Parent constructor, but keep in mind that that call basically ensures that the new object created is a valid Parent instance before being a child Instance. In my example if you were to not call the Parent constructor, the name and age properties would not be set on the Child instance, so the greet method would return I am child undefined and i'm undefined, far from what you would expect.
It's worthwhile exploring the different ways you can extend and add bits to an object in JavaScript.
Using constructors
(function (global) {
function SuperClass() { }
var p = SuperClass.prototype;
p.doSomething = function() {
console.log('do something (super)')
};
function OtherClass() {
SuperClass.call(this);
}
OtherClass.prototype = new SuperClass();
Window.OtherClass = OtherClass;
}(window));
var o = new OtherClass();
Using object.create (no double instantiation) - Not supported on all browsers.
(function (global) {
// SuperClass - superclass
function SuperClass() {
}
var p = SuperClass.prototype;
p.doSomething = function() {
console.log('do something (super)')
};
function OtherClass() {
SuperClass.call(this);
}
OtherClass.prototype = Object.create(SuperClass.prototype);
Window.OtherClass = OtherClass;
}(window));
Functional Mixins:
When you want to mixin a generic set of methods/properties into an object.
var mixin = function () {
this.methodA = function () {
};
this.methodA = function () {
};
return this;
}
var object = function () {
this.methodB = function () {
}
}
mixin.call(object.prototype);
A very good details explanation of all the methods:
http://javascriptweblog.wordpress.com/2011/05/31/a-fresh-look-at-javascript-mixins/

Categories

Resources