Classes and inheritance in Coffeescript - javascript

What on earth is going on here?
How can the Daughter-class contain data that's been set in Brother, and how should I make sure that data set in sibling classes doesn't interfere with eachother?
class Parent
data: {}
class Child extends Parent
age: 10
Son = new Child
Son.data.name = "John Doe"
Daughter = new Child
console.log Daughter.data # => { name: 'John Doe' }

The problem seems to be, that you're not using a constructor to initialize data for each instance. Instead, you're giving it an initial value that happens to sit on Animal which is mutable. Whenever you assign to instance.data.attribute, you are in fact modifying that shared object. If you had used an data: 1 instead, you would not have seen this sharing behavior.
This fixes your problem:
class Parent
constructor: () ->
#data = {}
Disclaimer: I'm not that well versed with JavaScript's prototypal inheritance, so the technical details I provided may not be correct, but the description of the phenomenon seems accurate.
Difference when compiled
class Parent
staticD: {}
constructor: ->
#data = {}
Compiles to:
Parent = (function() {
Parent.prototype.staticD = {};
function Parent() {
this.data = {};
}
return Parent;
})();
As you can see staticD is initalized only once at the creation of the "class", data on the other hand is initialized in the constructor and assigned a new, empty object every time an instance is created.

If you take your CS code and put it in the side-by-side editor on CoffeeScript's site (http://coffeescript.org/), you'll see that data is on the prototype of the Parent "class". Think of that prototype being the template for new functions (classes) that you create. That prototype either contains other functions or it contains variables available to all instances (like an OO static variable).
You're adding name to a "static" variable data. It will then be available to all instances that "derive" from Parent.
I'm not sure of the inner workings that go on there, but coming from an OO world, that's how I interpret it. I hope this helps.
GENERATED CODE VIA COFFEESCRIPT'S SITE
var Child, Daughter, Parent, Son,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
Parent = (function() {
function Parent() {}
Parent.prototype.data = {};
return Parent;
})();
Child = (function(_super) {
__extends(Child, _super);
function Child() {
return Child.__super__.constructor.apply(this, arguments);
}
Child.prototype.age = 10;
return Child;
})(Parent);
Son = new Child;
Son.data.name = "John Doe";
Daughter = new Child;
alert(Daughter.data.name);
UPDATE
Just noticed that the CS side-by-side window has a link feature. Here's a link to the side-by-side code.
UPDATE #2
In response to your question in the comments, I'm not sure exactly what you want to do, but you could do something like this:
class Parent
#data: {}
class Child extends Parent
constructor: (#name) ->
age: 10
sayHi: -> alert "Hi " + #name
Son = new Child "John Doe"
Daughter = new Child "Sarah Jane"
Son.sayHi()
Daughter.sayHi()
Perhaps keep the name variable (or the entire data variable) at the parent level and set it via a constructor and access it via a parent function.

Related

Javascript Prototypal Inheritance - Truly understanding the concept

I was looking at this video explanation(https://www.youtube.com/watch?v=qMO-LTOrJaE) of JS prototypal inheritance.
There's something I don't understand. Let me explain
var Bear = function(type) { //PARENT
this.type;
this.hasFur = true;
}
Bear.prototype.kingdom = 'Animalia'; //ASSIGNING TO PARENT'S PROTOTYPE
var Grizzly = function(type) { //CHILD
this.species = 'Brown Bear';
}
Grizzly.prototype = Object.create(Bear.prototype); //INHERITING FROM PARENT
var grizzly1 = new Grizzly('grizzly');
console.log(grizzly1.hasFur); //prints undefined //members in parent's constructor not accessible
console.log(grizzly1.kingdom); //prints Animalia //however, members in parent's prototype is accessible
But as soon as you add the following line to the Grizzly constructor,
var Grizzly = function(type){
Bear.call(this, type); //ADDED
this.species = 'Brown Bear';
}
you're able to access everything from the parent, not just it's prototype
console.log(grizzly1.hasFur); //prints true
console.log(grizzly1.kingdom); //prints Animalia
However, inheriting in the below fashion, gives the child access to everything in the parent even without the line //Bear.call(this) in the Child constructor.
Grizzly.prototype = new Bear();
So it truly inherits everything this way. Can someone explain what's this behavior and why it happens ?
Also what are the different ways of inheriting in JavaScript. Which one is the best to use considering best practices and why.
There's something I don't understand. Let me explain
var Bear = function(type) { //PARENT
this.type;
this.hasFur = true;
}
Bear.prototype.kingdom = 'Animalia'; //ASSIGNING TO PARENT'S PROTOTYPE
var Grizzly = function(type) { //CHILD
this.species = 'Brown Bear';
}
Grizzly.prototype = Object.create(Bear.prototype); //INHERITING FROM PARENT
var grizzly1 = new Grizzly('grizzly');
console.log(grizzly1.hasFur); //prints undefined //members in parent's constructor not accessible
console.log(grizzly1.kingdom); //prints Animalia //however, members in parent's prototype is accessible
In the code snippet shared above, grizzly1.hasFur is undefined as the constructor function for Bear is not yet executed. The line Grizzly.prototype = Object.create(Bear.prototype); just inherits the parent prototypal methods and properties.
But as soon as you add the following line to the Grizzly constructor,
var Bear = function(type) { //PARENT
this.type;
this.hasFur = true;
}
Bear.prototype.kingdom = 'Animalia'; //ASSIGNING TO PARENT'S PROTOTYPE
var Grizzly = function(type) { //CHILD
Bear.call(this, type); //ADDED
this.species = 'Brown Bear';
}
Grizzly.prototype = Object.create(Bear.prototype); //INHERITING FROM PARENT
var grizzly1 = new Grizzly('grizzly');
console.log(grizzly1.hasFur); //prints undefined //members in parent's constructor not accessible
console.log(grizzly1.kingdom);
grizzly1.hasFur is now true because now within the constructor function of grizzly, the constructor class for Bear is invoked changing its context using a call. The this. hasFur gets its true value assigned in this operation as here due to the changed context, this now refers to the instance of grizzly.
However, inheriting in the below fashion, gives the child access to everything in the parent even without the line //Bear.call(this) in the Child constructor.
Grizzly.prototype = new Bear();
What happens here is, a new instance of the Bear class is created. Now any instance of the class Bear can have access to the prototypal methods and internal properties defined while instantiating the constructor class i.e. function Bear. Now after the instance being created, this gets assigned to the prototypal chain of Grizzly. So any new instance of Grizzly not only access the internal properties of Grizzly, but also behaves as a new instance of the Bear class.
Also what are the different ways of inheriting in JavaScript
I would definitely suggest you to study design patterns. You can google out different books for it. I loved reading JavaScript: The Good Parts and Learning JavaScript Design Patterns. You might love some other books for clearing up your fundamentals. There are few countable things in Javascript like these, closures, etc., which needs crystal clear conceptions.
Which one is the best to use considering best practices and why.
The best practice in prototypal inheritance ,I prefer,is:
In the constructor class say A
function A () {
this.privateProp = something;
}
A.prototype.public = something;
So see declare only those properties and methods inside the constructor class, which you wanna keep private. Rest keep it exposed in prototype chain.
Hope this helps.
Check this out:
var Bear = function(type){ //PARENT
this.type;
this.hasFur = true;
}
alert(new Bear().hasFur);
See how this does gives you true in the alert box. Think, why is this working, and not for your example?
Thought about it?
It's because in this code:
var Bear = function(type){ //PARENT
this.type;
this.hasFur = true;
}
You're assigning the function to Bear, so it's accessible by new Bear() not Bear.prototype. This will work:
Bear.prototype.kingdom = 'Animalia'; //ASSIGNING TO PARENT'S PROTOTYPE
var Grizzly = function(type){ //CHILD
this.species = 'Brown Bear';
}
Grizzly.prototype = Object.create(new Bear()); // Modified line
var grizzly1 = new Grizzly();
alert(grizzly1.hasFur); // Prints true now.
alert(grizzly1.kingdom);

Understanding Prototypal Inheritance methodologies in JS

I have read every article and example on the first page of Google and I still am having a hard to completely understanding how to properly implement Prototypal Inheritance in JavaScript. The biggest challenge I'm facing is I am seeing many different ways to implement the inheritance.
First I will start with what I want to achieve if this was C#:
C#
class Base {
public string UI { get; set; } // Using a string just for simplicity
}
class Book : Base {
public Book(string title) {
this.title = title;
}
private string title { get; set; } // Title of book
}
Then I can instantiate a Book and be able to access UI on each instance:
var myBook = new Book("East of Eden");
myBook.UI = "some string"; // This work.. all Book instances have THEIR OWN UI string
JavaScript
Now lets say I have a base object in JS that I want all other objects to inherit from:
function Base() {
this.UI = {}
}
I then want another object type to inherit this model like this:
function Book(title){
this.title = title;
}
Book.prototype = new Base();
// Sometimes I have seen this line instead... nothing seems to work at all when I use this though, so I don't understand whats happening here
//Book.prototype = Object.create(Base.prototype);
Book.prototype.constructor = Book;
Book.prototype.getTitle = function(){
return this.title;
}
var myBook = new Book("East of Eden");
var anotherBook = new Book("Grapes of Wrath");
console.log(myBook.getTitle()); // East of Eden
myBook.UI.isRead = true;
console.log(myBook.UI);
console.log(anotherBook.getTitle()); // Grapes of Wrath
anotherBook.UI.isHardcopy = true;
myBook.UI.isRead = false;
console.log(anotherBook.UI); // This UI object has isRead on it as well!!! NOOOO
So this doesn't really work because both instances are sharing the same UI object, but what I want is for them to have their OWN instance of the UI object.
Another method I have seen is to not use the 'new' keyword at all and only use Object.create() to get new objects. However, I am not sure how I would implement my Base class with some subclass like Book and then create multiple instances of Book, each with their own UI properties.
Could someone please give me an example of how to inherit a base class and create instances of that subclass with their own UI objects? Thanks
EDIT
So would the "simple" way of achieve what I want just be to do something like:
var Base = {
UI: {}
}
function Book(title){
_.extend(this, Base);
this.title = title;
}
var myBook = new Book("East of Eden");
myBook.UI.prop = 5; // This works now but doesn't utilize true inheritance at all!
Prototypes are linked and not copied. This means that when you did:
function Base(){
this.UI = {}
}
Book.prototype = new Base();
Book.prototype.constructor = Book;
The prototype of your Book constructor will be a new instance of Base. All your instances of Book will have the same prototype, the same instance of Base. Since it's this object which holds the UI property, all Book instances will fallback to the same object property.
Think that your Prototype will be:
var proto = {
UI : { }
}
All your Book instances will have access to this object:
var a = new Book('East of Eden');
var b = new Book('Grapes of Wrath');
a.UI.prop = 'prop'; //proto.UI.prop === 'prop'
b.UI.prop === 'prop'; //because it's also proto.UI.prop
If you actually define a property on Book instances, say on its constructor:
function Book(title){
this.title = title;
this.UI = { };
}
You'll see that they are different objects:
a.UI !== b.UI //true
a.UI.prop = 'prop';
b.UI.prop !== b.UI; //true
Calling the constructor is the most obvious way to also initialize the properties on their children:
function Book(title){
Base.call(this);
this.title = title;
}
Regarding the difference between new Base() and Object.create(Base.prototype).
new Base() will initialize the object and call the constructor, while Object.create(Base.prototype) will do basically the same, except it won't call the constructor. This means, that the prototype won't have the properties set on the constructor (UI).
The biggest challenge I'm facing is I am seeing many different ways to implement the inheritance.
There really is only one correct way.
Use Object.create to establish inheritance:
Child.prototype = Object.create(Parent.prototype, {
constructor: {
value: Child,
configurable: true,
}
});
Then apply the parent constructor in the child constructor to the child instance:
function Child() {
Parent.call(this);
}
This is basically what happens under the hood if you'd use ES2015's new class syntax.
See Benefits of using `Object.create` for inheritance for more details on Object.create and why you want to use it in this case.

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/

How to call a parent method from child class in javascript?

I've spent the last couple of hours trying to find a solution to my problem but it seems to be hopeless.
Basically I need to know how to call a parent method from a child class.
All the stuff that I've tried so far ends up in either not working or over-writing the parent method.
I am using the following code to set up OOP in javascript:
// SET UP OOP
// surrogate constructor (empty function)
function surrogateCtor() {}
function extend(base, sub) {
// copy the prototype from the base to setup inheritance
surrogateCtor.prototype = base.prototype;
sub.prototype = new surrogateCtor();
sub.prototype.constructor = sub;
}
// parent class
function ParentObject(name) {
this.name = name;
}
// parent's methods
ParentObject.prototype = {
myMethod: function(arg) {
this.name = arg;
}
}
// child
function ChildObject(name) {
// call the parent's constructor
ParentObject.call(this, name);
this.myMethod = function(arg) {
// HOW DO I CALL THE PARENT METHOD HERE?
// do stuff
}
}
// setup the prototype chain
extend(ParentObject, ChildObject);
I need to call the parent's method first and then add some more stuff to it in the child class.
In most OOP languages that would be as simple as calling parent.myMethod()
But I really cant grasp how its done in javascript.
Any help is much appreciated, thank you!
ES6 style allows you to use new features, such as super keyword. super keyword it's all about parent class context, when you are using ES6 classes syntax. As a very simple example, checkout:
Remember: We cannot invoke parent static methods via super keyword inside an instance method. Calling method should also be static.
Invocation of static method via instance method - TypeError !
class Foo {
static classMethod() {
return 'hello';
}
}
class Bar extends Foo {
classMethod() {
return super.classMethod() + ', too';
}
}
console.log(Bar.classMethod()); // 'hello' - Invokes inherited static method
console.log((new Bar()).classMethod()); // 'Uncaught TypeError' - Invokes on instance method
Invocation of static method via super - This works!
class Foo {
static classMethod() {
return 'hello';
}
}
class Bar extends Foo {
static classMethod() {
return super.classMethod() + ', too';
}
}
console.log(Bar.classMethod()); // 'hello, too'
Now super context changes based on invocation - Voila!
class Foo {
static classMethod() {
return 'hello i am static only';
}
classMethod() {
return 'hello there i am an instance ';
}
}
class Bar extends Foo {
classMethod() {
return super.classMethod() + ', too';
}
}
console.log((new Bar()).classMethod()); // "hello there i am an instance , too"
console.log(Bar.classMethod()); // "hello i am static only"
Also, you can use super to call parent constructor:
class Foo {}
class Bar extends Foo {
constructor(num) {
let tmp = num * 2; // OK
this.num = num; // ReferenceError
super();
this.num = num; // OK
}
}
And of course you can use it to access parent class properties super.prop.
So, use ES6 and be happy.
Here's how its done: ParentClass.prototype.myMethod();
Or if you want to call it in the context of the current instance, you can do:
ParentClass.prototype.myMethod.call(this)
Same goes for calling a parent method from child class with arguments:
ParentClass.prototype.myMethod.call(this, arg1, arg2, ..) * Hint: use apply() instead of call() to pass arguments as an array.
Well in order to do this, you are not limited with the Class abstraction of ES6. Accessing the parent constructor's prototype methods is possible through the __proto__ property (I am pretty sure there will be fellow JS coders to complain that it's depreciated) which is depreciated but at the same time discovered that it is actually an essential tool for sub-classing needs (especially for the Array sub-classing needs though). So while the __proto__ property is still available in all major JS engines that i know, ES6 introduced the Object.getPrototypeOf() functionality on top of it. The super() tool in the Class abstraction is a syntactical sugar of this.
So in case you don't have access to the parent constructor's name and don't want to use the Class abstraction you may still do as follows;
function ChildObject(name) {
// call the parent's constructor
ParentObject.call(this, name);
this.myMethod = function(arg) {
//this.__proto__.__proto__.myMethod.call(this,arg);
Object.getPrototypeOf(Object.getPrototypeOf(this)).myMethod.call(this,arg);
}
}
Here's a nice way for child objects to have access to parent properties and methods using JavaScript's prototype chain, and it's compatible with Internet Explorer. JavaScript searches the prototype chain for methods and we want the child’s prototype chain to looks like this:
Child instance -> Child’s prototype (with Child methods) -> Parent’s prototype (with Parent methods) -> Object prototype -> null
The child methods can also call shadowed parent methods, as shown at the three asterisks *** below.
Here’s how:
//Parent constructor
function ParentConstructor(firstName){
//add parent properties:
this.parentProperty = firstName;
}
//add 2 Parent methods:
ParentConstructor.prototype.parentMethod = function(argument){
console.log(
"Parent says: argument=" + argument +
", parentProperty=" + this.parentProperty +
", childProperty=" + this.childProperty
);
};
ParentConstructor.prototype.commonMethod = function(argument){
console.log("Hello from Parent! argument=" + argument);
};
//Child constructor
function ChildConstructor(firstName, lastName){
//first add parent's properties
ParentConstructor.call(this, firstName);
//now add child's properties:
this.childProperty = lastName;
}
//insert Parent's methods into Child's prototype chain
var rCopyParentProto = Object.create(ParentConstructor.prototype);
rCopyParentProto.constructor = ChildConstructor;
ChildConstructor.prototype = rCopyParentProto;
//add 2 Child methods:
ChildConstructor.prototype.childMethod = function(argument){
console.log(
"Child says: argument=" + argument +
", parentProperty=" + this.parentProperty +
", childProperty=" + this.childProperty
);
};
ChildConstructor.prototype.commonMethod = function(argument){
console.log("Hello from Child! argument=" + argument);
// *** call Parent's version of common method
ParentConstructor.prototype.commonMethod(argument);
};
//create an instance of Child
var child_1 = new ChildConstructor('Albert', 'Einstein');
//call Child method
child_1.childMethod('do child method');
//call Parent method
child_1.parentMethod('do parent method');
//call common method
child_1.commonMethod('do common method');
In case of multiple inheritance level, this function can be used as a super() method in other languages. Here is a demo fiddle, with some tests, you can use it like this, inside your method use : call_base(this, 'method_name', arguments);
It make use of quite recent ES functions, an compatibility with older browsers is not guarantee. Tested in IE11, FF29, CH35.
/**
* Call super method of the given object and method.
* This function create a temporary variable called "_call_base_reference",
* to inspect whole inheritance linage. It will be deleted at the end of inspection.
*
* Usage : Inside your method use call_base(this, 'method_name', arguments);
*
* #param {object} object The owner object of the method and inheritance linage
* #param {string} method The name of the super method to find.
* #param {array} args The calls arguments, basically use the "arguments" special variable.
* #returns {*} The data returned from the super method.
*/
function call_base(object, method, args) {
// We get base object, first time it will be passed object,
// but in case of multiple inheritance, it will be instance of parent objects.
var base = object.hasOwnProperty('_call_base_reference') ? object._call_base_reference : object,
// We get matching method, from current object,
// this is a reference to define super method.
object_current_method = base[method],
// Temp object wo receive method definition.
descriptor = null,
// We define super function after founding current position.
is_super = false,
// Contain output data.
output = null;
while (base !== undefined) {
// Get method info
descriptor = Object.getOwnPropertyDescriptor(base, method);
if (descriptor !== undefined) {
// We search for current object method to define inherited part of chain.
if (descriptor.value === object_current_method) {
// Further loops will be considered as inherited function.
is_super = true;
}
// We already have found current object method.
else if (is_super === true) {
// We need to pass original object to apply() as first argument,
// this allow to keep original instance definition along all method
// inheritance. But we also need to save reference to "base" who
// contain parent class, it will be used into this function startup
// to begin at the right chain position.
object._call_base_reference = base;
// Apply super method.
output = descriptor.value.apply(object, args);
// Property have been used into super function if another
// call_base() is launched. Reference is not useful anymore.
delete object._call_base_reference;
// Job is done.
return output;
}
}
// Iterate to the next parent inherited.
base = Object.getPrototypeOf(base);
}
}
How about something based on Douglas Crockford idea:
function Shape(){}
Shape.prototype.name = 'Shape';
Shape.prototype.toString = function(){
return this.constructor.parent
? this.constructor.parent.toString() + ',' + this.name
: this.name;
};
function TwoDShape(){}
var F = function(){};
F.prototype = Shape.prototype;
TwoDShape.prototype = new F();
TwoDShape.prototype.constructor = TwoDShape;
TwoDShape.parent = Shape.prototype;
TwoDShape.prototype.name = '2D Shape';
var my = new TwoDShape();
console.log(my.toString()); ===> Shape,2D Shape
There is a much easier and more compact solution for multilevel prototype lookup, but it requires Proxy support. Usage: SUPER(<instance>).<method>(<args>), for example, assuming two classes A and B extends A with method m: SUPER(new B).m().
function SUPER(instance) {
return new Proxy(instance, {
get(target, prop) {
return Object.getPrototypeOf(Object.getPrototypeOf(target))[prop].bind(target);
}
});
}
more flexible answer with classic js.
You define "_parent = A.prototype;" in the child class, then you can call parent's methods with apply:
class A{
_msg='A';
_msgOnlyA=' great from A';
constructor(){
}
hello(){
console.log('hello '+this._msg+', '+this._msgOnlyA);
}
};
class B extends A{
_parent = A.prototype;
_msg='B';
constructor(){
super();
}
hello(){
this._parent.hello.apply(this, arguments);
console.log('hello '+this._msg);
}
};
var b = new B();
b.hello();
While you can call the parent method by the prototype of the parent, you will need to pass the current child instance for using call, apply, or bind method. The bind method will create a new function so I doesn't recommend that if you care for performance except it only called once.
As an alternative you can replace the child method and put the parent method on the instance while calling the original child method.
function proxy(context, parent){
var proto = parent.prototype;
var list = Object.getOwnPropertyNames(proto);
for(var i=0; i < list.length; i++){
var key = list[i];
// Create only when child have similar method name
if(context[key] !== proto[key]){
let currentMethod = context[key];
let parentMethod = proto[key];
context[key] = function(){
context.super = parentMethod;
return currentMethod.apply(context, arguments);
}
}
}
}
// ========= The usage would be like this ==========
class Parent {
first = "Home";
constructor(){
console.log('Parent created');
}
add(arg){
return this.first + ", Parent "+arg;
}
}
class Child extends Parent{
constructor(b){
super();
proxy(this, Parent);
console.log('Child created');
}
// Comment this to call method from parent only
add(arg){
return super.add(arg) + ", Child "+arg;
}
}
var family = new Child();
console.log(family.add('B'));

Javascript inheritance: call super-constructor or use prototype chain?

Quite recently I read about JavaScript call usage in MDC
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/call
one linke of the example shown below, I still don't understand.
Why are they using inheritance here like this
Prod_dept.prototype = new Product();
is this necessary? Because there is a call to the super-constructor in
Prod_dept()
anyway, like this
Product.call
is this just out of common behaviour? When is it better to use call for the super-constructor or use the prototype chain?
function Product(name, value){
this.name = name;
if(value >= 1000)
this.value = 999;
else
this.value = value;
}
function Prod_dept(name, value, dept){
this.dept = dept;
Product.call(this, name, value);
}
Prod_dept.prototype = new Product();
// since 5 is less than 1000, value is set
cheese = new Prod_dept("feta", 5, "food");
// since 5000 is above 1000, value will be 999
car = new Prod_dept("honda", 5000, "auto");
Thanks for making things clearer
The answer to the real question is that you need to do both:
Setting the prototype to an instance of the parent initializes the prototype chain (inheritance), this is done only once (since the prototype object is shared).
Calling the parent's constructor initializes the object itself, this is done with every instantiation (you can pass different parameters each time you construct it).
Therefore, you should not call the parent's constructor when setting up inheritance. Only when instantiating an object that inherits from another.
Chris Morgan's answer is almost complete, missing a small detail (constructor property). Let me suggest a method to setup inheritance.
function extend(base, sub) {
// Avoid instantiating the base class just to setup inheritance
// Also, do a recursive merge of two prototypes, so we don't overwrite
// the existing prototype, but still maintain the inheritance chain
// Thanks to #ccnokes
var origProto = sub.prototype;
sub.prototype = Object.create(base.prototype);
for (var key in origProto) {
sub.prototype[key] = origProto[key];
}
// The constructor property was set wrong, let's fix it
Object.defineProperty(sub.prototype, 'constructor', {
enumerable: false,
value: sub
});
}
// Let's try this
function Animal(name) {
this.name = name;
}
Animal.prototype = {
sayMyName: function() {
console.log(this.getWordsToSay() + " " + this.name);
},
getWordsToSay: function() {
// Abstract
}
}
function Dog(name) {
// Call the parent's constructor
Animal.call(this, name);
}
Dog.prototype = {
getWordsToSay: function(){
return "Ruff Ruff";
}
}
// Setup the prototype chain the right way
extend(Animal, Dog);
// Here is where the Dog (and Animal) constructors are called
var dog = new Dog("Lassie");
dog.sayMyName(); // Outputs Ruff Ruff Lassie
console.log(dog instanceof Animal); // true
console.log(dog.constructor); // Dog
See my blog post for even further syntactic sugar when creating classes. http://js-bits.blogspot.com/2010/08/javascript-inheritance-done-right.html
Technique copied from Ext-JS and http://www.uselesspickles.com/class_library/ and a comment from https://stackoverflow.com/users/1397311/ccnokes
The ideal way to do it is to not do Prod_dept.prototype = new Product();, because this calls the Product constructor. So the ideal way is to clone it except for the constructor, something like this:
function Product(...) {
...
}
var tmp = function(){};
tmp.prototype = Product.prototype;
function Prod_dept(...) {
Product.call(this, ...);
}
Prod_dept.prototype = new tmp();
Prod_dept.prototype.constructor = Prod_dept;
Then the super constructor is called at construction time, which is what you want, because then you can pass the parameters, too.
If you look at things like the Google Closure Library you'll see that's how they do it.
If you have done Object Oriented Programming in JavaScript, you will know that you can create a class as follows:
Person = function(id, name, age){
this.id = id;
this.name = name;
this.age = age;
alert('A new person has been accepted');
}
So far our class person only has two properties and we are going to give it some methods. A clean way of doing this is
to use its 'prototype' object.
Starting from JavaScript 1.1, the prototype object was introduced in JavaScript. This is a built in object that
simplifies the process of adding custom properties and methods to all instances of an object.
Let's add 2 methods to our class using its 'prototype' object as follows:
Person.prototype = {
/** wake person up */
wake_up: function() {
alert('I am awake');
},
/** retrieve person's age */
get_age: function() {
return this.age;
}
}
Now we have defined our class Person. What if we wanted to define another class called Manager which inherits some properties from Person. There is no point redefining all this properties again when we define our Manager class, we can just set it to inherit from the class Person.
JavaScript doesn't have built in inheritance but we can use a technique to implement inheritance as follows:
Inheritance_Manager = {};//We create an inheritance manager class (the name is arbitrary)
Now let's give our inheritance class a method called extend which takes the baseClass and subClassas arguments.
Within the extend method, we will create an inner class called inheritance function inheritance() { }. The reason why we are using this inner
class is to avoid confusion between the baseClass and subClass prototypes.
Next we make the prototype of our inheritance class point to the baseClass prototype as with the following code:
inheritance.prototype = baseClass. prototype;
Then we copy the inheritance prototype into the subClass prototype as follows: subClass.prototype = new inheritance();
The next thing is to specify the constructor for our subClass as follows: subClass.prototype.constructor = subClass;
Once finished with our subClass prototyping, we can specify the next two lines of code to set some base class pointers.
subClass.baseConstructor = baseClass;
subClass.superClass = baseClass.prototype;
Here is the full code for our extend function:
Inheritance_Manager.extend = function(subClass, baseClass) {
function inheritance() { }
inheritance.prototype = baseClass.prototype;
subClass.prototype = new inheritance();
subClass.prototype.constructor = subClass;
subClass.baseConstructor = baseClass;
subClass.superClass = baseClass.prototype;
}
Now that we have implemented our inheritance, we can start using it to extend our classes. In this case we are going to
extend our Person class into a Manager class as follows:
We define the Manager class
Manager = function(id, name, age, salary) {
Person.baseConstructor.call(this, id, name, age);
this.salary = salary;
alert('A manager has been registered.');
}
we make it inherit form Person
Inheritance_Manager.extend(Manager, Person);
If you noticed, we have just called the extend method of our Inheritance_Manager class and passed the subClass Manager in our case and then the baseClass Person. Note that the order is very important here. If you swap them, the inheritance
will not work as you intended if at all.
Also note that you will need to specify this inheritance before you can actually define our subClass.
Now let us define our subClass:
We can add more methods as the one below. Our Manager class will always have the methods and properties defined in the Person class because it inherits from it.
Manager.prototype.lead = function(){
alert('I am a good leader');
}
Now to test it let us create two objects, one from the class Person and one from the inherited class Manager:
var p = new Person(1, 'Joe Tester', 26);
var pm = new Manager(1, 'Joe Tester', 26, '20.000');
Feel free to get full code and more comments at:
http://www.cyberminds.co.uk/blog/articles/how-to-implement-javascript-inheritance.aspx

Categories

Resources