Understanding prototypal inheritance javascript - javascript

This is sort of a follow up of from this question: Python like inheritance for JavaScript
But I phrased it wrong and made it seem like I wanted classical inheritance in JavaScript when I just wanted to figure out how to do it similarly to Python.
This is what I have so far but it isn't working as I would like it to.
var util = require("util")
function FirstClass() {
this.name = "First Class";
}
FirstClass.prototype.sayName = function(){
this.callFunction("some_function", "hello")
}
FirstClass.prototype.callFunction = function(){
var func = arguments[0];
var args = Array.prototype.slice.call(arguments).slice(1, arguments.length)
if (this[func] !== undefined){
this[func].apply(null, args);
}
}
function SubClass(){}
util.inherits(SubClass, FirstClass)
SubClass.prototype.some_function = function(msg){
console.log(msg, this.name) // "hello undefined"
}
var sub_class = new SubClass();
sub_class.sayName();
When I try sub_class.sayName() It calls correctly and inherited sayName right, but when I try using the this keyword to show the name it doesn't work and prints undefined next to 'hello', so how would I fix it so it will show 'hello FirstClass'?
I was thinking this have all the variables and objects that FirstClass has since it inherits from it but it doesn't. Is that how prototypal inheritance is suppose to work? If so is there any way I can view/change parent variables from the child class?
I've tried looking up prototypal inheritance for JavaScript to figure it out but I'm not quite grasping the concept since I'm use to classical inheritance. Does anyone know how to inherit from the parent class and change it's variables from a child class?
Also if anyone has a good link to look at so I can understand prototypal inheritance better for future references that would be great.

You are missing this part:
function SubClass(){
FirstClass.apply(this);
}
This would be the equivalent to a super invocation in traditional class inheritance.

Your problem lies here: this[func].apply(null, args);
It should read: this[func].apply(this, args);

Here is a simplified example of how to inherit and extend a class. I very highly recommend checking Javascript Design Patterns for much better examples of how to create Classes with inheritance.
Now, as I was not familiar with what util was supposed to be doing, this example demonstrates how to achieve the result with native JS and no helpers:
JSFiddle here: http://jsfiddle.net/YAj5R/
function FirstClass() {
this.name = "First Class";
}
FirstClass.prototype.sayName = function () {
this.callFunction("some_function", "hello")
}
FirstClass.prototype.callFunction = function () {
var func = arguments[0];
var args = Array.prototype.slice.call(arguments).slice(1, arguments.length)
if (this[func] !== undefined) {
this[func].apply(this, args);
}
}
function SubClass() {
var parent = new FirstClass();
// this is lightweight example of an "extend" method
for(var attr in parent) {
// if this subclass has not over-written an attr,
// copy the attributes of FirstClass to SubClass
if(!this[attr]) {
this[attr] = parent[attr];
}
}
return this;
}
SubClass.prototype.some_function = function (msg) {
console.log(msg, this.name);
}
var sub_class = new SubClass();
sub_class.sayName();

Related

What would be the equivalent of `instanceof` when using functional inheritance?

In JavaScript there's a pattern to achieve inheritance called "Functional inheritance" described in chapter 5 of Crockfords "JavaScript: the good parts".
One of the disadvantages of the pattern -- as compared to using the pseudo-classical pattern -- is that we lose the ability to distinguish types using the instanceof operator.
Is there any way to achieve the same goal? How can we know that two objects are somehow related because they are of the same parent/base "type"?
Also how can we tell even though they are descendants of the same type they are different types themselves?
I don't know if not being able to use instanceof is a big loss but it doesn't seem like it is.
Notes
For those who are not familiar with Crockford's explanation, you can see an example at: JSFiddle, taken from here.
The instanceof operator is not special. You can implement it yourself as explained on the Mozilla Developer Network. See the accepted answer to the following question for more details:
JavaScript inheritance and the constructor property
Here's how the instanceof operator can be implemented in JavaScript:
function instanceOf(object, constructor) {
while (object != null) {
if (object == constructor.prototype) { //object is instanceof constructor
return true;
} else if (typeof object == 'xml') { //workaround for XML objects
return constructor.prototype == XML.prototype;
}
object = object.__proto__; //traverse the prototype chain
}
return false; //object is not instanceof constructor
}
Want to implement instanceOf for functional inheritance? That's easy to do too:
var object = child({ name: "a functional object" });
alert(object.instanceOf(child)); // true
alert(object.instanceOf(base)); // true
alert(object.sayHello()); // Hello, I'm a functional object
function base(spec) {
var that = {};
that.name = spec.name;
that.constructors = [base];
that.instanceOf = instanceOf;
return that;
}
function child(spec) {
var that = base(spec);
that.sayHello = sayHello;
that.constructors.push(child);
return that;
function sayHello() {
return "Hello, I'm " + this.name;
}
}
function instanceOf(constructor) {
return this.constructors.indexOf(constructor) >= 0;
}
Of course, in real functional programming there's no need to use instanceof at all.
So imagine we have these:
mammal { giveBirth }
reptile { layEgg }
cat : mammal { purr, playWithChildren }
dog : mammal { bark }
lion : mammal { purr }
(cat inherits mammal and implements purr() etc...)
Now imagine you have an array of animals.
What I think you're asking is how do we tell if animals[0] is a cat.
The desire to know if animals[0] is a cat comes from the fact we know that cats can do certain things. Instead of knowing if animals[0] is a cat what we really want to know is can animals[0] purr. Perhaps animals[0].purr !== undefined is more accurate than knowing if it is a cat. This does mean that we need to check for each of the functions rather than the container concept of a cat which we know implements several functions but it makes the implementation more robust and future proof (consider if we only cared about purring and lions were added to the types of animals later).
As for the question about inheritance again I would suggest that we don't need to know if the animal is a mammal we need to know if they giveBirth. This would again ensure that our implementation is more future proof so that when we add marsupial later all of our logic around giving birth rather than laying an egg still stands.
Store a parent object in the object, then
if (obj1.parentObject == obj2.parentObject) {//Do your things}
There are no certain types and distinction though inctanceof in "Functional inheritance"("JavaScript: the good parts"). It's about an exchange and relation between anonymous functions, which are generating objects, usually, with a private functionality. The logical hierarchy of those function is set with conditional preference. That functions can call each other, extend "parent" object methods, expand its functionality.
For example, in "functional inheritance" creating a new type, which is called "Mammal", would look like:
var mammal = function (spec) {
var that = {};
that.get_.name = function () {
return spec.name;
};
that.says = function () {
return spec.saying || '';
};
return that;
};
var myMammal = mammal({name: 'Herb'});
By some conditional agreements we can accept it as a parent type(class).
Now we can create another anonymous function that will be responsible for subtype(subclass) of "Mammal" type(class). This function will call "parent" function mammal() to get the object with basic functionality:
var cat = function (spec) {
spec.saying = spec.saying || 'meow';
var that = mammal(spec);
that.purr = function (n) {
var i, s = '';
for (i = 9; i < n; i += 1) {
if (s) {
s +=
}
s += 'r';
}
return s;
};
that.get_name = function () {
return that.says() + ' ' + spec.name + ' ' + that.says();
};
return that;
};
var myCat = cat({name: 'Henrietta'});

Javascript - transform object in class

I'm new in JS and i'm used to traditional OOP languages, so i'm having a hard time making some things work properly.
Here is my example :
var myObject = {
prop:'something';
callme:function () {
console.log('you called me');
}
}
firstObj = myObject;
firstObj.prop1 = 'new thing';
secondObj = myObject;
secondObj.prop1 = 'second thing';
Obviously the 'secondObj' overrides what 'fristObj' did before. How can i convert the 'myObject' object so it can work like a class , so i can create individual new instances of it ?
Thanks !
To create a 'class' in javascript you create a function which by convention has its first character capitalized.
function MyClass() { }
var obj = new MyClass();
To attach methods to this you add it to MyClass's prototype.
MyClass.prototype.callme = function () {
console.log('you called me');
}
To add properties use this to refer to this instance of the class.
function MyClass() {
this.prop = 'something';
}
So all together:
function MyClass() {
this.prop = 'something';
}
MyClass.prototype.callme = function () {
console.log('you called me');
}
// Remember to use var to declare variables (or they are global)
var firstObj = new MyClass();
firstObj.prop = 'new thing';
var secondObj = new MyClass();
secondObj.prop = 'second thing';
There is a style of JS programming where you just make objects and functions which return objects. In your case, make myObject into a function which returns the hash. It will return a new one each time it's called.
var myObject = function() {
return {
prop: 'something';
callme: function () {
console.log('you called me and prop is', this.prop);
}
};
}
firstObj = myObject();
firstObj.prop1 = 'new thing';
firstObj.callme();
secondObj = myObject();
secondObj.prop1 = 'second thing';
secondObj.callme();
In addition to the two good answers you already have, I wanted to point out that if you are ready to use edge stuff, ES6, the next JavaScript spec, includes classes.
Using transpilers like babel, you can already write ES6 code then compile it so that it can run on all browsers. It works increadibly well, especially when combined with tools like webpack that automates the process, and raises more and more adepts. It is the future, and clearly worse a try (classes are just the tip of the iceberg).
You can read more on ES6 classes here. Here is one of the example they give:
class Polygon {
constructor(height, width) {
this.height = height;
this.width = width;
}
get area() {
return this.calcArea()
}
calcArea() {
return this.height * this.width;
}
}
A theoretical answer to a practical question. JavaScript is more traditional (take for example SmallTalk - one of the JavaScript grandparents) in terms of OOP than most of the current OOP languages. It is prototype-based, meaning that objects inherit from other objects. The constructor function is an unpleasant legacy (also called "classical inheritance") for the sake of typical OOP class imitation (in the way class is just a fabric for objects in most popular OOP, the typical JavaScript object is a fabric for other object). Analogous example could be the Io language (given for simplicity). IMO there is no need for separate objects' fabrics like class.

Prototype chain: call "super" method over multiple levels

I have got the following prototype chain
SuperSuperClass
SuperClass
Class
each with a method named do.
What is the common approach for calling the respective super class method?
For the moment I use <ClassName>.prototype.__proto__.<methodName>.call(this) but that looks odd.
Using the following code the console prints (as expected):
Class.prototype.do
SuperClass.prototype.do
SuperSuperClass.prototype.do
SuperSuperClass = function SuperSuperClass() {}
SuperSuperClass.prototype.do = function() {
console.log('SuperSuperClass.prototype.do');
};
function SuperClass() {
SuperSuperClass.call(this);
}
SuperClass.prototype = Object.create(SuperSuperClass.prototype);
SuperClass.prototype.constructor = SuperClass;
SuperClass.prototype.do = function() {
console.log('SuperClass.prototype.do');
SuperClass.prototype.__proto__.do.call(this);
};
function Class() {
SuperClass.call(this);
}
Class.prototype = Object.create(SuperClass.prototype);
Class.prototype.constructor = Class;
Class.prototype.do = function() {
console.log('Class.prototype.do');
Class.prototype.__proto__.do.call(this);
};
var objClass = new Class();
objClass.do();
JSFiddle
What is the common approach for calling the respective super class method?
Use <SuperClassName>.prototype.<methodName>.call(this). It's not only shorter, but also has the benefit of working in environments that don't support the non-standard __proto__ property.

Cleanest way to write prototype inheritance in JS

Somewhat of a JS newbie still, I'm trying to understand the best / cleanest way to use prototypes and inheritance.
Normally I write object/prototype definitions like this:
var Foo = function(data) {
this.data = data;
};
Foo.prototype = {
someMethod: function() {
return "whatever";
}
};
I like this because I often am using namespace objects a few layers deep, so it might actually look more like this:
App.Model.FooModel = function(){...};
App.Model.FooModel.prototype = {...};
This is nice because I don't have to type out the full name of every method to write the prototype, just the name, ie. someMethod: function(){} instead of App.Model.FooModel.prototype.someMethod = function(){}.
Now, the problem I've run into is I'm not sure how to do this with inheritance in JS. I can get inheritance working fine if I do it like this:
var Child = function(){...};
Child.prototype = new Parent;
Child.prototype.someMethod = function(){...};
...but now in a more complicated application we're back to writing out the full name of the object for every method, which I find both tedious and hard to read.
So, my question is: is there a clean, straightforward way to write prototypes that inherit from another object, except to attach all child methods using the full name of the object?
Thanks!
Well, this being javascript, you can always write your own:
function construct ( parent, fn, attr ) {
fn.prototype = new parent();
for (var x in attr) {
fn.prototype[x] = attr[x];
}
return fn;
}
You can do the hasOwnProperty check if you want but the above is simplest implementation for clarity. This function encapsulates the three steps into one. You can now simply do:
var Foo = construct(
Parent,
function(data) {
this.data = data;
},
{
someMethod: function() {
return "whatever";
}
}
);
If you don't like the syntax you can always come up with a better one. An alternative implementation is to simply implement the attr extension part and do the inheritance normally:
function extend (obj, attr) {
for (var x in attr) {
obj.prototype[x] = attr[x];
}
return obj;
}
Again, simplified for clarity. So the syntax now becomes:
var Foo = function(){...};
Foo.prototype = new Parent;
extend(Foo.prototype,{
someMethod : function(){...}
});

Javascript apply — Inheriting classes

The code below is adapted from this answer
function MessageClass() {
var self = this;
this.clickHander = function(e) { self.someoneClickedMe = true; };
var _private = 0;
this.getPrivate = function() { return _private; };
this.setPrivate = function(val) { _private = val; };
}
ErrorMessageClass.prototype = new MessageClass();
function ErrorMessageClass() {
MessageClass.apply(this, arguments);
}
var errorA = new ErrorMessageClass();
var errorB = new ErrorMessageClass();
errorA.setPrivate('A');
errorB.setPrivate('B');
console.log(errorA.getPrivate());
console.log(errorB.getPrivate());
The original post did not have the MessageClass.apply(this, arguments); since the purpose was to show how inheritance can go wrong in Javascript.
My question is, is saying: ErrorMessageClass.prototype = new MessageClass(); before the ErrorMessageClass constructor has even been declared bad practice? My understanding is that calling undeclared identifiers like that causes a silent declaration to occur, with the result being placed on the global window object, which I understand is bad.
Is this form:
function ErrorMessageClass() {
MessageClass.apply(this, arguments);
}
ErrorMessageClass.prototype = new MessageClass();
considered to be better practice? This link shows the code written as it was originally above, which is why I even tried it. Does this blogger know something I don't (quite likely)?
EDIT
Lots of great info in the answers below, but I did want to highlight this link which really explains things perfectly
Usually, to avoid this confusion, you would just attach the prototype after, but as Adam Rackis pointed out, function declarations are hoisted, like var statements.
However, you should not instantiate the base object as the prototype. If your base object takes arguments, what are you supposed to use? Use an empty "surrogate" constructor
// Used to setup inheritance
function surrogate () {};
function MessageClass() {
var self = this;
this.clickHander = function(e) { self.someoneClickedMe = true; };
var _private = 0;
this.getPrivate = function() { return _private; };
this.setPrivate = function(val) { _private = val; };
}
// The key steps to creating clean inheritance
surrogate.prototype = MessageClass;
// Sets up inheritance without instantiating a base class object
ErrorMessageClass.prototype = new surrogate();
// Fix the constructor property
ErrorMessageClass.prototype.constructor = ErrorMessageClass
function ErrorMessageClass() {
MessageClass.apply(this, arguments);
}
There's much more to be said. http://js-bits.blogspot.com/2010/08/javascript-inheritance-done-right.html
It works because function declarations are evaluated first. If you tried to move these classes under an object literal "namespace" the first version would fail.
I personally find the second method to be much easier to read - also, don't forget to set the sub-class' prototype.constructor property back to itself. Personally, I use an inherits() method on the Function prototype which wraps up essentially the type of code you're using here.

Categories

Resources