Prototypical Inheritance calls constructor twice - javascript

I'm working on a JavaScript project that uses Prototypical Inheritance. The way that I decided to use it is the following:
var MySuperClass = function (param) {
this.prop = param;
};
MySuperClass.prototype.myFunc = function () {
console.log(this.prop);
};
var MySubClass = function (param) {
MySuperClass.call(this, param);
};
MySubClass.prototype = new MySuperClass();
MySubClass.prototype.constructor = MySubClass;
var obj = new MySubClass('value');
obj.myFunc();
With the emphasis on the inheritance.
The issue with this is that if I put a console.log in the constructor of each class (the super and the sub), the super class is called twice, once when it is passed into the subclass with MySubClass.prototype = new MySuperClass(); without any parameters and once with parameters when it is 'constructor stolen' in the constructor of the sub class.
This can cause errors if I then try to save those parameters (meaning that I have to add logic to deal with empty params).
Now if I do this:
var MySubClass = function (param) {
MySuperClass.call(this, param);
};
MySubClass.prototype = MySuperClass;
MySubClass.prototype.constructor = MySubClass;
Everything seems to work correctly but I've never seen anyone do this before (in my Googl'ing).
Can anyone explain to me if and how the 2nd one is incorrect (it seems to be similar to the Crockford inheritance function) and how to fix the 1st one to not fire twice if it is please?

Doing this is not a correct solution:
MySubClass.prototype = MySuperClass;
You're setting the function itself as the prototype instead of the prototype object, so you're not inheriting what you'd expect.
But you are right. Doing this does invoke the constructor, which can cause problems.
MySubClass.prototype = new MySuperClass();
The solution is to use Object.create to set up the inheritance. It gives you a new object that inherits from the object provided, but doesn't invoke any constructor.
MySubClass.prototype = Object.create(MySuperClass.prototype);
Now you have an object assigned to MySubClass.prototype that inherits from MySuperClass.prototype, but you never had to actually invoke the constructor.
Non ES5 compliant implementations won't support Object.create, but you can make a (partial) shim for it.
if (!Object.create) {
Object.create = function(proto) {
function F(){}
F.prototype = proto;
return new F();
};
}
Again, this is not a full shim, but it emulates just enough to be able to make inherited objects without having to invoke the constructor that references the prototype object.

Related

understanding simple class emulator in JavaScript

Recently I started to learn a bit more advanced JavaScript (as far I only used jQuery for some simple tasks) and bought a book of Alex MaxCaw "JavaScript Web Applications". The first chapter treats about creating simple class emulator. I understand almost everything except for two lines of code marked with comments down below:
var Class = function(parent) {
var _class = function() {
this.init.apply(this, arguments);
};
if(parent) {
var subclass = function() {};
subclass.prototype = parent.prototype;
_class.prototype = new subclass();
};
_class.prototype.init = function() {};
_class.fn = _class.prototype;
//????
_class.fn.parent = _class;
//????
_class._super = _class.__proto__;
return _class;
};
Can anyone tell me what is purpose of these two lines? I'll be very thankfull.
Walking through the code:
Class is defined as a function that calls init with the arguments provided it. This means you can call it with standard constructor syntax using new eg. var instance = new Thingy() and get the init function called with the proper this value.
If you pass a parent class in, your class gets that class's prototype property added to the prototype chain of a new empty object which it uses as its prototype property. A more succinct way of doing this in modern browsers is _class.prototype = Object.create(parent.prototype);
The init function is defined. This should likely be overridden with more useful initialization code after a _class instance is created (or the code should be changed to allow the passing in of an init function when you create a Class... or allow the instance to walk the prototype chain to look for other init functions.
_class.fn is created to provide a reference to the _class constructor's prototype function.
_class.fn.parent is created to provide a reference back to the constructor. This may be useful if you are applying the prototype in some other context and want a reference back to the prototype's constructor.
_class._super is assigned the internal, non-standard __proto__ property of the constructor. Remember that constructors are functions and, in Javascript, functions are objects. This means they have their own internal prototypes. The earlier references to prototype are the prototype assigned to objects created with this constructor NOT the constructor's prototype itself. All functions inherit from Function.prototype, which is where they get bind, apply, etc. _super in this case is just a reference to Function.prototype.
As to when this type of _super is used, one could imagine doing the following:
function Maker(){ //this will be called as a constructor, ie. with new
var fun = function(){}; //Make a function
fun.__proto__ = this.__proto__; //yuck. Set the function's this value to the instance
return fun; //return the function
}
Maker.prototype={say:function(){console.log("Javascript is fun!.. And weird.")}};
var fun = new Maker();
fun.say() //"Javascript is fun!.. And weird."
console.log(fun.__proto__) // Object{say:function}
console.log(fun.bind) // undefined!!
Woah! What just happened?
In fact, you replaced your functions internal prototype with an Object. This allows you to build up interesting prototype chains and interact with both functions and objects in a similar way. Note, however, that the link with Function.prototype has been severed, which is why we don't have access to bind. However let's fix it with more prototype magic!
function FunctionConnector(obj){
for (var prop in obj){
if(obj.hasOwnProperty(prop){
this.prop=obj.prop
}
}
}
FunctionConnector.prototype=Function.prototype;
Maker.prototype=new FunctionConnector({say:function(){
console.log("Javascript is fun!.. And weird.")
}});
var fun = new Maker();
fun.say() //"Javascript is fun!.. And weird."
console.log(fun.__proto__) // Object{say:function}
console.log(fun.bind) // function bind(){ [native code] }
Now what is that FunctionConnector? It takes an object and, when called as a constructor, returns an object that both has all the properties of the passed object AND inherits from Function.prototype. As you can see, our access to bind has returned (Of course we also could have made do with our original implementation and just Function.prototype.bind.called our way to victory).
With this new pattern in hand it may be clearer what _super in your code does, namely it references the built in prototype of the _class constructor you are making (In our example the instance of FunctionConnector would be _super). This reference could be used to patch the prototype at runtime, call methods with apply or anything else you can due with a reference to an object.
This is, as you may have noticed a little hackish, especially since __proto__ is nonstandard. But it's also somewhat neat if you enjoy the patterns it allows. I'd recommend only doing something like this if you are very confident in your knowledge of Javascript inheritance, and perhaps not even then unless you are in charge of your entire code base.
From what i know, fn is just an alias to the prototype property
And about the _super, that one is for referencing to the "class" from which you are inheriting
Here's more about the use of _super and js inheritance: article

Purpose of this Javascript prototype snippet

Sorry I can't phrase this better. But I ran across some code like the following:
MyObject.prototype = Object.create(MyObject.prototype);
MyObject.prototype.constructor = MyObject;
And I just can't seem to figure out what it does. MyObject is defined above it something like this:
function MyObject(options) {
this.someProp = someDefault;
this.otherProp = process(options.something);
// etc...
}
and it's always called as a constructor. I'm just wondering what benefit those first two lines provide and if it's a known pattern in Javascript.
I just can't seem to figure out what it does
It creates a new object that inherits from [the old] MyObject.prototype via Object.create and then overwrites MyObject.prototype with that. It also explicitly adds a .constructor property which actually should be existing already.
I'm just wondering what benefit those first two lines provide
None, unless before that snippet someone has corrupted the prototype (like MyObject.prototype = Object.prototype) and this is an attempt to fix it.
…and if it's a known pattern in Javascript.
Not like this. Using Object.create to set up the prototype chain for inheritance between constructor-defined "classes" is a known pattern, but then the constructors would be different on each side of the assignment.
The two lines of code provided seem to be an incorrect attempt of the use of prototypal inheritance, but I see where you're going with this and what you're trying to accomplish.
As we know, there are two ways in JavaScript to define objects that have properties and methods as members - the object literal notation and function notation. Using object literal notation, we don't have immediate access to the new keyword (think of this like using abstract classes in Java or C#). With function notation, we have access to the new keyword because the initial declaration of an object as a function serves as our constructor.
In ECMAScript 5, The Object object was given a method called create that provided developers a simple way to create a new object from an existing object declared with the object literal notation. (See documentation here). However, objects created in function notation have problems with this method because they are Function objects. The Object.create method is a great way to use simple inheritance, allowing access to the base properties and methods.
With function notation, once the new keyword is used, the result is not a function, but rather an object. For example, I can test this:
var Obj = function(){};
console.log(typeof Obj) // "function"
console.log(typeof new Object()); // "object"
Because of this, you can only inherit once (meaning the child object cannot be derived from):
var MyObject = new Object();
var anotherObj = new MyObject() // throws exception
To alleviate this problem, you need to follow three steps:
Create your child object in function notation (so you can create new instances of it using the new keyword and inherit from it).
Set the child object's prototype (an object) to the result of a new instance of the base object (which will be an object as well).
Set the constructor of the child object (which happens to be on the object's prototype) back to reference the Function of itself (which is a function prior to instantiation). If you don't do this, the constructor will remain an object, which cannot spawn new instances.
From here, you can create new instances of both the child and parent objects and derive from both, using the pattern. Here's a practical example:
var Vehicle = function(){};
Vehicle.prototype.start = function() {
return this.make + " " + this.model + " " + "started";
}
var Car = function(color, make, model) {
this.color = color;
this.make = make;
this.model = model;
}
Car.prototype = new Vehicle();
Car.prototype.constructor = Car;
var myCar = new Car("red", "chevy", "aveo");
myCar.start(); //"chevy aveo started"
I really don't see any benefit in doing that.
What it's doing is providing the new object with the previous objects methods. But it's coming from the same object...
Here is a good example of JS inheritance:
http://jsfiddle.net/aDCmA/2/
var App = (function(){
var Being = function() {
this.living = true;
this.breathes = function () {
return true;
};
};
var Robert = function() {
this.blogs = true;
this.getsBored = function () {
return "You betcha";
}
};
Robert.prototype = new Being();
return {
Being: Being,
Robert: Robert,
being: function(){ return new Being(); },
robert: function(){ return new Robert(); }
}
}());
Here is another question that is similar: inherit prototype methods from other classes without overriding own prototype methods
Credit to Robert Nyman for originally blogging about it: http://robertnyman.com/2008/10/06/javascript-inheritance-how-and-why/
Let's see line by line:
MyObject.prototype = Object.create(MyObject.prototype);
This redefines MyObject.prototype to an object that inherits from MyObject.prototype. This is unusual, because it makes no sense to inherit from itself.
MyObject.prototype.constructor = MyObject;
Since the previous line overwrote MyObject.prototype, this is just fixing the constructor property that was lost in the process.
I can think of one scenario where tht might be useful: if some code before that messed up with MyObject.prototype, for example assigning the prototype of another constructor to it:
MyObject.prototype = SomethingElse.prototype; // wrong way to do inheritance.
Then the code you posted would be an attempt to fix it.
This is perfectly valid Javascript.
Any javascript function (say Func)can be used as a constructor and the constructor invocation also requires a prototype property (i.e. F.prototype or the prototype associated with the function) . Thus (almost) every function has a prototype property. The value of this property (i.e. Func.prototype).
Now the value of this prototype associated with the function is an object itself that has a single non enumerable property called constructor. And the value of this constructor property is the function object (i.e. F itself).
Lets take an example.
Say I construct a function Func
var Func = function() {
//your definition
};
Now since this can be invoked as a constructor it has to have a prototype property Func.prototype lets call this proto.
proto = Func.prototype;
Now the prototype has a single property (that is non enumerable) called constructor. This constructor has a value that is equal to the function object itself.
Dont believe me check it like this
Func.prototype.constructor === Func // =>true
Will always return true for any function.
Now from the code you explained :
So basically these two lines
MyObject.prototype = Object.create(MyObject.prototype);
MyObject.prototype.constructor = MyObject;
are modifying the value of the prototye to have a constructor property with the value of MyObject that is defined. But that would have happened anyways in the normal course of things. But the reason could be that maybe the prototype of the object has been changed earlier from the class it has been inherited from. In that case would those two lines make sense.
Hope that helps :)

Do we really have to change to Object.create?

I have a question for you
As I know, new operator works this way
function fakeNew(Ctor) {
var instance = Object.create(Ctor.prototype);
instance.constructor();
// I skip the conditional for simplicity
return instance;
}
It all begin when I did a Object.create polifill so I could create objects without using new.
Object.create = function(proto) {
function F() { }
F.prototype = proto;
return new F();
}
I started creating a lot of objcts and prototiping them, but as many times then need to initializa its properties I did a .init() method to them
var base = {
init: function() {
EmitterMixin.call(this);
return this;
}
};
var obj = Object.create(base).init();
But of course, I had to rembember to return this always from .init() and many times I forget it or worst, I forgot to call .init(). So trying to simplify object initialization I wanted to create a global helper to do it: invoke Object.create, invoke the initializer function and return this.
function create(proto) {
var child = Object.create(proto);
child.init();
return child;
}
Then was when I wanted to hit my head against the wall when I realized what I was doing was virtually what new operator does but a lot slower. And in case the polifill applies I would even use new under the hood.
So I ask myself, what benefits throwing new? It's notably quicker on main browsers and because of javascript nature we usually need to call a initualizer function, something than new does from it's begining.
And worst, I've noticed than I used two different types of objects, "abstract" and "instances", the bigger difference is than for instances I had to invoke .init() while with abstracts it was not necesasary because they will only be used to be prototypes of other objects. And I've already seen this pattern while using new:
function Foo() { }
Foo.prototype.method = function() { ... };
function Bar() { }
// "abstract" doesnt invoke initializer
Bar.prototype = Object.create(Foo.prototype);
Bar.prototype.other = function() { ... };
// "instance", the constructor is called as initializer
var obj = new Bar();
Is there really a benefit if we stop seeing new? are we sure it's not a higher-level tool than simplifies something we'll have to do anyway?
What pros/cons do you see about new and Object.create?
I have tried both approaches and I don't personally see any problem with the traditional approach using new. The main argument for Object.create is that it makes the prototypal inheritance more clear - you don't have to understand the intricacy of the prototype property on function constructors and how that relates to the actual prototype of the object. But it does require that initialization be a separate step.
My preferred approach is to combine the two approaches, e.g.:
function Animal(name) {
this.name = name || null;
}
Animal.prototype.eat = function() {
console.log('yum');
}
function Cat(name) {
Animal.call(this, name);
}
Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.constructor = Cat;
Cat.prototype.meow = function() {
console.log('meow');
}
var garfield = new Cat('garfield');
garfield.eat();
garfield.meow();
Object.create is better for inheritance here than Cat.prototype = new Animal() for two reasons:
If you wanted to require the name parameter (throwing an exception if it wasn't passed), you could do so and the inheritance (Cat.prototype = Object.create(Animal.prototype)) would still work.
If you forgot to call the Cat constructor from the Animal constructor, all of the properties that would have been created by the Animal constructor will be undefined instead, allowing you to quickly realize the mistake.
Although this approach (using constructor functions and new) is less "purely" prototypal, it's still prototypal inheritance and as long as you understand how to use it correctly it works just fine, and requires a little less typing than the Object.create approach.
I wrote some other notes about this in the documentation for my Javascript OO library, simpleoo. (Note: I may be changing the API soon for that library; I'm linking to it mainly because the documentation discusses some of these concepts in more detail.)

In Javascript, why does the constructor property point to the base-most constructor in the prototype chain?

I'm curious about this design of Javascript, and perhaps any reasons for this architecture or design patterns that can be employed to take advantage of this.
The constructor property of an object is always a reference to the function that created that object, correct?
However, take this code:
function base()
{
this.SayHi = function ()
{
window.alert('Hi');
};
}
function subclass()
{
this.SayBye = function ()
{
window.alert('Bye');
};
}
subclass.prototype = new base();
var s = new subclass();
s.SayHi();
s.SayBye();
window.alert(s.constructor);
The last line will echo the constructor for base, even though we know subclass was called to create the object (otherwise SayBye would not work).
One potential work-around would be to simply do:
subclass.prototype.constructor = subclass;
Perhaps a more concise way of asking my question is why is s.constructor equal to subclass.prototype.constructor and not subclass.constructor, since s is an instanceof subclass. Thanks!
All objects inherit a constructor property from their prototype.
Source.
That's just how it works. You often do see people explicitly setting the constructor property to something that seems more intuitive to them.

Baffling JavaScript Inheritance Behavior

<disclaimer>
What follows is the fruits of a thought experiment. What I'm doing
isn't the issue; the symptoms are. Thank you.
</disclaimer>
I've finally wrapped my head around constructors, prototypes, and prototypal inheritance in JavaScript. But the SomethingSpectactular method in the sample below bugs me:
function FinalClass() {
return {
FinalFunction : function() { return "FinalFunction"; },
TypeName : "FinalClass",
SomethingSpectacular : function() {
return FinalClass.prototype.SubFunction.call(this);
}
}
}
FinalClass.prototype = new SubClass();
FinalClass.constructor = FinalClass;
var f = new FinalClass();
The reasons this bugs me are:
JavaScript apparently doesn't scan the prototype chain the same way for methods as it does for properties. That is, f.SubFunction() generates an error.
To get to a method on a prototype, you have to go through at least 3 dot operations every time you want to do it. FinalClass DOT prototype DOT Subfunctino DOT call. You get the point.
Base class (prototype) methods aren't showing up in Intellisense the way I'd expect them to. This is highly annoying.
So the thought experiement was to determine what would happen if I wrote a version of inherits that inserted stub functions onto the subclass that delegated back to the prototype for you. For example, it would automatically create the following function and add it to FinalClass:
function SubFunction() { SubClass.prototype.SubFunction.call(this); }
Now, I've got just about everything mapped out and working. The inherits method, which is an extension to both Object.prototype and Function.prototype, takes a Function as its sole argument. This is the base class. The subclass is determined by analyzing Object.prototype.inherits.caller.
From there, I set the prototype and constructor on the subclass, and then start analyzing the methods on the subclass's new prototype. I build an array containing the methods on both the prototype and the base class's public interface. The end result is a nice array that contains the methods that are exposed through either the prototype or by the base class constructor's return statement.
Once I have that, I start looking for each method on the subclass. If it's not there, I add it to the subclass with the same name and signature. The body of the method, however, simply forwards the call to the base class.
Now, I can step through all this code and it works marvelously, up until I instantiate instances of the subclasses. That's when things get wonky. Here's what I've observed using Visual Studio 2008 (SP1) and Internet Explorer 8:
Prior to instantiation, BaseClass exposes no public methods. This is to be expected. The methods exposed via a class constructor's return statement won't appear until it's instantiated. I'm good with that.
Prior to instantiation, SubClass exposes the methods from BaseClass. This is exactly what I expected.
Once I declare an instance of BaseClass, it has all the members I would expect. It has its typeName and BaseFunction methods.
Once I declare an instance of SubClass, it has only those methods returned by its constructor's return statement. No members from the base class are present. All the work that was done in the inherits method to map base class methods to the subclass appears to have been lost.
The big mystery for me here is the disappearance of the methods that I added to SubClass during the execution of inherits. During its execution, I can clearly see that SubClass is being modified, and that BaseClass's functions are being propagated. But the moment I create an instace of SubClass, that information is no longer present.
I am assuming this has something to do with the constructor, or order of events, or something else that I am simply not seeing.
A Final Note: This project arose as an effort to understand the complexities of JavaScript and how its prototypal inheritance system works. I know there are existing libraries out there. I know I'm reinventing the wheel. I'm reinventing it on purpose. Sometimes, the best way to understand a thing is to build it yourself. This has already been a tremendous learning experience, but I'm just stumped at this one particular point.
THE CODE
sti.objects.inherits = function inherits(baseClass) {
var subClass = sti.objects.inherits.caller;
var baseClassName = sti.objects.getTypeName(baseClass);
var methods = sti.objects.getMethods(baseClass);
if(!sti.objects.isDefined(baseClass.typeName))
baseClass.typeName = baseClassName;
var subClass = sti.objects.inherits.caller;
var subClassName = sti.objects.getTypeName(subClass);
var temp = function() {};
temp.prototype = new baseClass();
subClass.prototype = temp.prototype;
subClass.constructor = subClass;
subClass.typeName = subClassName;
subClass.baseClass = baseClass.prototype; // Shortcut to the prototype's methods
subClass.base = baseClass; // Cache the constructor
for(var index = 0; index < methods.items.length; index++) {
var resource = methods.items[index].getFunction();
var methodName = methods.items[index].getName();
if(methodName != "" && ! sti.objects.isDefined(subClass[methodName])) {
var method = sti.objects.createOverride(baseClassName, resource);
subClass[methodName] = method;
if(typeof subClass.prototype[methodName] == "undefined") {
subClass.prototype[methodName] = method;
}
}
}
}
Object.prototype.inherits = sti.objects.inherits;
Function.prototype.inherits = sti.objects.inherits;
function BaseClass() {
return {
A : function A() {return "A";}
};
}
function SubClass() {
inherits(BaseClass);
return {
B : function B() { return "B"; }
}
}
var b = new BaseClass();
var s = new SubClass();
Your constructors are not working as constructors. When you use the new keyword Javascript creates the new object and expects your constructor to populate it with members etc. Your constructors are returning another new object, not related to the object which is associated with the constructor usage, thus the prototype is not working.
Change your constructor to something like
function FinalClass() {
this.FinalFunction = function() { return "FinalFunction"; };
this.TypeName = "FinalClass";
this.SomethingSpectacular = function() {
return FinalClass.prototype.SubFunction.call(this);
};
}
and you should see the expected inheritance behaviour. This is because the FinalClass method in this case alters the contextual object created via the 'new' mechanism. Your original method is creating another object which is not of type FinalClass.

Categories

Resources