Call super class constructor when multiple inheritance in DOJO - javascript

I have an object that inherit from 2 others object.
I'm using manually call for constructor because i want to manipulate the parameters i am sending to the super classes (see '-chains-')
define([...], function(...) {
return declare("myClass", [base1, base2],
{
"-chains-":
{
constructor: "manual"
},
constructor: function (params) {
this.inherited(arguments, [ params.x, params.y, ... ]); // just for the example
}
});
});
The problem is that I am doing something wrong here with the syntax because my super classes constructors are not being called at all.
When i'm removing the -chains- and the this.inherited... the super classes constructors are being called but without my parameters manipulation.
Found Workaround
Instead of the this.inherited(...) in myClass constructor we write
base1.prototype.constructor.apply(this, [paramsForBase1]);
base2.prototype.constructor.apply(this, [paramsForBase2]);
But still happy to hear the Dojo way

There is no Dojo way I'm afraid. The main advantage of automatic constructor inheritance is that it will call all constructors.
However, if you set it to manual, then it will only call the constructor of the last inherited class in the list. In your case, the constructor of base2 will be called, but not the one from base1.
The reason for this is that eventually, your class can only have one method of each kind, so if both base1 and base2 have the same method, then it will override them in the same order you provided the inheritance array. Meaning that it will first contain base1.constructor, and in the next step it will be overriden by base2.constructor.
EDIT:
If you don't want to manually call the constructors of all base classes by yourself, you could create a loop. All base constructors are actually available in a meta object. It's a bit hacky, but this.constructor._meta.parents provides an array of all constructors, so you can simply loop over it, for example:
var inheritAllConstructors = function(object, arguments) {
for (var idx = 0; idx < object.constructor._meta.parents.length; idx++) {
object.constructor._meta.parents[idx].apply(object, arguments);
}
};
And then you can use it like this:
constructor: function(name) {
inheritAllConstructors(this, ["custom", "arguments"]);
},
A full example can be found on JSFiddle: http://jsfiddle.net/n7wnvbu1/

Related

Difference between class method vs className.prototype method in JS

I am wondering what's the difference between setting methods via Class body vs prototype binding in JS. (if any)
I am currently working on Eloquent JavaScript example and I was surprised when author firstly created a class with bunch of methods inside its body and then created another method with className.prototype.methodName = function(){}
class Cat {
constructor() {
}
method1() {
console.log("m1");
}
}
Cat.protoype.method2 = function() {
console.log("m2");
}
The most obvious difference is:
You can mutate the prototype of every class with the second method (including native ones), while the first syntax only works for declaring your own classes (but on the other hand it keeps things clean & structured).
There are other differences, that you can ignore in most cases:
1) Class methods are not enumerable, while setting a property directly makes it enumerable.
This would be more equivalent to the class syntax:
Object.defineProperty(Cat.protoype, "method2", {
value() {
console.log("m2");
},
enumerable: false, // it's the default value, this is just for clarity
writable: true,
configurable: true,
});
2) super is only accessible in methods added during declaration (both in objects and classes) of the object / class itself.
3) The .name of the function is "test" in the first, and "anonymous" in the second case. That can be changed by making the function non anonymous, e.g. function method2() { ... }
I hope this helps: "Changes to the Object prototype object are seen by all objects through prototype chaining, unless the properties and methods subject to those changes are overridden further along the prototype chain. This provides a very powerful although potentially dangerous mechanism to override or extend object behavior."
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype

Javascript Inheritance calling parent's non default constructor

I know that classical pattern for inheritance with prototype is based to set the object prototype of the constructor function.
However my willing is to have the possibility to call the parent constructor from the derived class constructor with some arguments that are not available before the call.
This is well accomplished in Java/Python/PHP with super(...) or Parent.__init__(...) method.
However in plain Javascript (not coffescript or similar) there is no way to do that ( parent.apply(this,arguments) does but not it does not setup the prototype).
After some readings I've got this solution, adding the "inherits" method to the prototype of Function.
This simply add the definition of super to the derived function in order to initialize the prototype according some parameters.
Function.prototype.inherits=function(parent)
{
var ctor=this;
var p=Object.create(parent);
ctor.super=function()
{
parent.apply(p,arguments);
}
ctor.prototype=p;
}
//testing
function A(x)
{
this.x=x;
}
function B(y)
{
B.super(y*2);//Here "super" is available and I can pass parameters.
this.y=y;
}
B.inherits(A);//here I define the inheritance
a=new A(3);
b=new B(5);
console.log(a);//returns { x: 3 }
console.log(b);//returns { y: 5 }
console.log(b.x);//returns 10
console.log(a instanceof A);//returns true
console.log(b instanceof B);//returns true
In this way I've got the behaviour that I expected.
My question is: what are the drawbacks of this solution? Are there more efficent solutions to the same problem ? Is this solution cross-browser?
PS: I've invented it by myself :)
EDIT: in order to avoid collisions with other libraries I could define a standalone function like this that accomplish the same target.
function inherits(klass,parent)
{
var p=Object.create(parent);
klass.super=function()
{
parent.apply(p,arguments);
}
klass.prototype=p;
}
And in the testing after definition of B simply call
inherits(B,A);
EDIT 2:
After Moolamaduck consideration I have rewritten the code in order to solve the problem of shared prototype. The result is pretty simple to use and elegant (IMHO).
https://stackoverflow.com/a/33270707/76081
Here's a minimal example which achieves what you want (calling a parent constructor from within the constructor of a derived class):
var Shape = function(sides) {
this.sides = sides;
};
var Square = function(size) {
/* Just call the parent constructor function with `this` as context. */
Shape.call(this, 4);
this.size = size;
};
/* Set up the prototype chain. Use a shim for `Object.create` if you want. */
Square.prototype = Object.create(Shape.prototype);
That's all there is to it: call the parent constructor with the object being constructed as context, and set up the prototype chain.
There is one serious flaw in the code you posted. Namely, you are calling the parent constructor with the prototype of the derived class as context, rather than the object being constructed. This means that members which the parent constructor initializes will be updated on the prototype of all instances of the derived class, and so all instances will be updated. This is not what you want.
To illustrate the problem:
Function.prototype.inherits=function(parent)
{
var ctor=this;
var p=Object.create(parent);
ctor.super=function()
{
parent.apply(p,arguments);
}
ctor.prototype=p;
}
function A(x)
{
this.x=x;
}
function B(y)
{
B.super(y*2);
this.y=y;
}
B.inherits(A);
var b1 = new B(1);
var b2 = new B(2);
alert(b1.x); // displays "4" instead of "2"!
One drawback could be that extending prototype of built-in objects like Function or Array has the possibility to clash with third party scripts that run on the page. If two scripts try to overwrite the same prototype, you can get unexpected results.
In terms of browser compatibility, it appears that the weakest link is Object.create, which is not supported in IE 8 and older. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create#Browser_compatibility
It seems like you're looking for a general pattern in which to recreate the classical Object Orientated paradigm in JavaScript (including use of super).
A few years ago John Resig (the creator of jQuery) suggested a set of functions that allows you to mimic this in Javascript.
http://ejohn.org/blog/simple-javascript-inheritance/
However, for a couple of reasons (including use of the arguments.callee property) this in now considered deprecated, but can still act as a good base.
There are a number of improvements that have been suggested which replace the arguments.callee property, including:
Is John Resig's Javascript inheritance snippet deprecated?
https://codereview.stackexchange.com/questions/30018/improving-on-john-resigs-simple-javascript-inheritance-avoiding-new
If you're looking for a reliable way to recreate classical Object Orientation in JavaScript, I would research further into improvements on John's original code (the guy knows what he's talking about and it's a good base to build on).
After Moolamaduck consideration I have rewritten the code in order to solve the problem of shared prototype.
The result is pretty simple to use and elegant (IMHO).
Here is it, with testing:
function inherits(ctor,parent)
{
ctor.prototype=Object.create(parent.prototype);
ctor._super=function()
{
parent.apply(this,arguments);
}
}
//testing
function A(x)
{
this.x=x;
};
function B(y)
{
B._super.call(this,y*2);//Here "_super" is available (after calling inherits) and I can pass parameters to the parent constructor.
this.y=y;
};
inherits(B,A);// Here we call inherits, after this parent will be available in the B constructor
a=new A(3);
b=new B(5);
console.log(a);//returns A {x: 3}
console.log(b);//returns B {x: 10, y: 5}
console.log(b.x);//returns 2*5=10
console.log(a instanceof A);//returns true
console.log(b instanceof B);//returns true
//post instantiation method definition and inheritance
A.prototype.test=function(){console.log(this.x+1);};
a.test();//returns 3+1=4
b.test();//returns 2*5+1=11
var b1 = new B(1);
var b2 = new B(2);
console.log(b1.x);//returns 2
console.log(b2.x);//returns 4

Why would these three lines of code result in the definition of a Javascript "class"?

The Javascript microlibrary augment.js is sometimes used to include OOP-like features in Javascript code. Despite working with Javascript on a daily basis I am still somewhat naive about the inner workings of the language, so I often rely on or borrow from patterns from other libraries to avoid pitfalls.
One function in the augment.js library is defclass, which is quite short:
augment.defclass = function (prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
};
My question is: how is this anything like defining a class? It looks like all it does is 1) set the prototype of the input's constructor to be the input itself, and then 2) return the constructor. What does that have to do with defining a class (or something like a class)?
A class defined like this:
var Thing = augment.defclass({
constructor: function () {
this.x = 5;
},
getX: function () {
return this.x;
}
});
A typical JavaScript constructor:
function Thing() {
this.x = 5;
}
Thing.prototype.getX = function () {
return this.x;
};
They both have the same effect, but the defclass version looks more familiar to users of other languages. One extracts the constructor from the prototype, and the other puts the prototype on the constructor.
how is this anything like defining a class?
The question you need to answer first is: What is a class in Javascript?
From: Object vs Class vs Function
As you must already be aware by now there are no classes in
JavaScript. Instead functions in JavaScript may be made to behave like
constructors by preceding a function call with the new keyword. This
is known as the constructor pattern.
From: JavaScript: The Good Parts Douglas Crockford, O'Reilly Media, 8 May 2008, page 29
If a function is invoked with the new prefix, then a new object will
be created with a hidden link to the value of the function's prototype
member, and this will be bound to that new object.
So again there are no classes - you have functions that can be invoked with new. If those functions have a prototype property, then the new objects created are inheriting from that prototype.
Everything you need to do to define a Javascript function to be used as a constructor is setting the properties you want instances to inherit on its prototype property and (as you pointed out in your question) augment.defclass is doing that.
The reason for having such a function has been already explained by minitech in his answer.

JavaScript Code Architecture - Use Constructor Functions Or Not

Please help me decide whether I should use a function's prototype object and the "new" keyword or completely stay away from constructor functions.
Situation:
Function called widget() that will be called 10-15 times to initialize each widget on the page. widget() contains quite a few internal methods.
Each time widget() is called, the function needs to return an object that acts as an API to operate on the widget.
Question
1) Do I put all the internal methods inside Widget() under its prototype property? It does not make sense but the main reason for this is to not re-instantiate the internal functions every time widget() is called.
But if I do put the internal functions in prototype, each instantiated w object (w = new Widget();) has access to internal private methods.
2) If I stay away from constructor functions and new keyword and structure my code as down below, how do I fix the performance concern of the internal functions getting re-instantiated every time widget() is called.
function widget()
{
var returnObj = {};
/* Add internal functions but this will be re-instantiated every time */
return returnObj;
}
You have a bit of a tradeoff here. As you seem to already understand, methods you put on the .prototype are publicly available, but that is the most efficient places to put methods as they are automatically added to all new copies of that object in a very efficient manner. When using .prototype for methods, there is only one copy of your methods and a reference to that single copy is automatically added to all new instantiations of that object.
But, javascript doesn't have private methods built-in and the only work-around for that involves not using the .prototype for them or for any methods that need to call the private methods.
This article by Doug Crockford is a pretty good description of how you can create privacy for either data or methods in any object.
In either case, I don't see any reason to avoid using the new keyword to create new objects. You can make either .prototype or private methods work with new.
But, if you want to achieve truly private methods, then you can't use .prototype for either the private methods or any methods that need to access them so you have to decide which is more important to you. There is no single correct answer because your need for privacy is situation-specific.
In my coding, I generally don't enforce privacy and I do use .prototype and new. I designate "non-public" methods on the prototype by starting their name with an underscore. This is a notational convention, not an access enforcement scheme.
In answer to your second question about avoiding the new operator and reinstantiating methods, I'd just ask why you're doing this? What are you gaining? I'm not aware of any downsides to using new. As best I understand your decision about whether to use .prototype vs. manually create/assign methods in your constructor should be about the need for private methods.
FYI, 15 objects is hardly going to create a significant difference in performance either way here. I would evaluate your need for true privacy and make your decision based on that. If you HAVE to enforce privacy, then go with the Crockford method for implementing private methods. If you don't HAVE to have true privacy, then use .prototype. I don't see a reason here to avoid using new in either case.
You can use a metaconstructor* pattern to get around this.
function defineCtor(metaCtor) {
var proto = new metaCtor();
var ctor = proto.hasOwnProperty('constructor') ?
proto.constructor : new Function();
return (ctor.prototype = proto).constructor = ctor;
}
Now you have a function that constructs constructors (or more accurately constructs prototypes and returns constructors).
var Widget = defineCtor(function() {
function doInternalStuff() {
// ...cant see me
}
// this function ends up on the prototype
this.getFoo = function() { return doInternalStuff(); };
});
// ...
var myWidget = new Widget();
Explanation
defineCtor takes a single anonymous function as a property. It invokes the function with new, creating an object. It assigns the object as the prototype property of a new constructor function (either an empty function, or the generated prototype object's own constructor property), and returns that function.
This provides a closure for your internal functions, addressing your question 1, and sets up the constructor/prototype pair for you, addressing question 2.
Comparison
Compare the defineCtor technique to the following two examples.
This example uses the prototype, and has problem 1: the internal stuff is not encapsulated.
function Widget(options) {
this.options = options;
}
Widget.prototype = {
getFoo: function() {
return doInternalStuff();
}
};
// How to encapsulate this?
function doInternalStuff() { /* ... */ }
This example sets up everything in a constructor, and has problem 2: each time it constructs an object, it instantiates new function objects for each property.
function Widget(options) {
this.options = options;
function doInternalStuff() { /* ... */ }
this.getFoo = function() {
return doInternalStuff();
};
}
This example uses the technique described above to provide encapsulation while still leveraging the prototype:
var Widget = defineCtor(function() {
// ^
// This function runs once, constructing the prototype.
// In here, `this` refers to the prototype.
// The real constructor.
this.constructor = function(options) {
// In function properties, `this` is an object instance
// with the outer `this` in its prototype chain.
this.options = options;
};
function doInternalStuff() { /* ... */ }
this.getFoo = function() { return doInternalStuff(); };
});
// ...
var myWidget = new Widget();
This approach has a few benefits, some more immediately obvious than others.
It provides encapsulation. You could do this by wrapping the first "comparison" example in an immediately invoked function, but this approach may be cleaner and more easily "enforced" in a team setting.
It's extensible. You can give your "metaconstructor" functions their own prototypes, with function properties like "extends", "mixin", etc. Then, inside the body of metaCtor, you can write things like this.extends(BaseWidget). The defineCtor API never needs to change for any of this to happen.
It "tricks" Google Closure Compiler, Eclipse, jsdoc, etc. into thinking you are defining the actual constructor function rather than a "meta function." This can be useful in certain situations (the code is "self-documented" in a way these tools understand).
* As far as I know, the word "metaconstructor" is completely made up.

javascript inheritance

I know there is a lot of similar questions are tons of great answers to this. I tried to look at the classical inheritance methods, or those closure methods etc. Somehow I consider they are more or less "hack" methods to me, as it doesn't really what the javascript is designed to do. (Welcome anybody correct me if I am wrong).
OK, as long as it works, I satisfy with the classical inheritance pattern like:
PARENTClass = function (basevar) { do something here; };
PARENTClass.prototype = { a: b, c: d}; // prototype is auto gen
// Inheritance goes here
CHILDClass = function (childvar) { do something; };
CHILDClass.prototype = new PARENTClass(*1); // Actual inheritance to the prototype statement
// Instance
CHILDInstance = new CHILDClass(whatever);
Above is somehow, to my understanding the inheritance of JS. But one scenario I have no idea how to implement, is that what if I want to do some initializing DURING object creation (ie, within constructor), and the new object can be used right away.... My illustration on problem might not be too clear, so let me use the following C# Psuedo to explain what I want to do:
class PARENT {
public PARENT (basevar) { ... }
}
class CHILD : PARENT {
public CHILD (basevar) : PARENT (basevar) // constructor of child, and call parent constructor during construct.
{ ... }
}
For some reason (like init. UI elements), putting them in constructor seems the best way to do. Anyone have idea on how can I do it.
PS: in the *1, I have no idea what I should put there.
PS2: The above situation I DID found the jquery.inherit library can do, I just wonder if not using library can achieve it.
PS3: Or my understanding is wrong. Since javascript is not intended to mimick OOP (that's why i call it hack), what is the "CORRECT" logic to implement this.
It is not a hack as such; JavaScript is a prototyped language, as defined by Wikipedia as where:
..classes are not present, and behavior reuse (known as inheritance in class-based languages) is performed via a process of cloning existing objects that serve as prototypes.
As it says, classes are not used in JavaScript; each object that you create is descended from the JavaScript Object; all objects in JavaScript have the prototype object, and all instances of objects you create 'inherit' methods and properties from their object's prototype object. Take a look at the MDC prototype object reference for more information.
As of this, when you call the line:
CHILDClass.prototype = new PARENTClass();
This allows the CHILDClass object to add methods and properties to its prototype object from the PARENTClass object, which creates an effect similar to the idea of inheritance present in class-based languages. Since the prototype object affects every instance created of that object, this allows the parent object's methods and properties to be present in every instance of your child object.
If you want to call your parent class's constructor in your child class's constructor, you use the JavaScript call function; this allows you to call the parent class's constructor in the context of the child class's constructor, therefore setting the newly prototyped properties in your child class to what they are set as in the parent class.
You also do not need to put anything where you have specified the *1, since that line is merely used to add the methods and properties to the child class's prototype object; however, bear in mind that it calls the parent class's constructor, so if there are any arguments that are fundamental in the operation of the parent class constructor, you should check that these are present so as to avoid JavaScript errors.
You can manually invoke the parent constructor in the subclass constructor like this:
CHILDClass = function (basevar) {
PARENTClass.call(this, basevar);
// do something;
};
The trick here is using the call method, which allows you to invoke a method in the context of a different object. See the documentation of call for more details.
JavaScript has no built-in support for inheritance hierarchies as type extension is supposed to be done via aggregation, ie adding desired functionality directly to the object itself or its prototype if the property is to be shared between instances.
Nevertheless, JS is powerful enough to make implementing other forms of object construction possible, including classical inheritance.
Given a clone function - which is enough to add 'true' prototypical inheritance, and not JavaScript's bastardization thereof - your exampe can be implemented like this:
function ParentClass(baseVar) {
// do stuff
}
// don't overwrite the prototype object if you want to keep `constructor`
// see http://joost.zeekat.nl/constructors-considered-mildly-confusing.html
ParentClass.prototype.a = 'b';
ParentClass.prototype.c = 'd';
function ChildClass(childVar) {
// call the super constructor
ParentClass.call(this, childVar);
}
// don't inherit from a ParentClass instance, but the actual prototype
ChildClass.prototype = clone(ParentClass.prototype);
ChildClass.prototype.e = 'f';
It's also possible to add some syntactic sugar for class-based inheritance - my own implementation can be found here.
The example from above would then read
var ParentClass = Class.extend({
constructor: function(baseVar) {
// do stuff
},
a: 'b',
c: 'd'
});
var ChildClass = ParentClass.extend({
e: 'f'
});
I've got a lightweight javascript OOP wrapper that provides 'Class-like' inheritance where you can override base methods or call base constructors or members.
You define your classes like this:
//Define the 'Cat' class
function Cat(catType, firstName, lastName)
{
//Call the 'Animal' constructor.
Cat.$baseNew.call(this, firstName, lastName);
this.catType = catType;
}
//Extend Animal, and Register the 'Cat' type.
Cat.extend(Animal, { type: 'Cat' }, {
hello: function(text)
{
return "meaoow: " + text;
},
getFullName: function()
{
//Call the base 'Animal' getFullName method.
return this.catType + ": " + Cat.$base.getFullName.call(this);
}
})
//It has a built-in type system that lets you do stuff like:
var cat = new Cat("ginger", "kitty", "kat");
Cat.getType() // "Cat"
cat.getBaseTypesAndSelf() // ["Cat","Animal","Class"]
cat.getType() // "Cat"
cat.isTypeOf(Animal.getType()) // "True"
var dynamicCat = Class.createNew("Cat", ["tab","fat","cat"])
dynamicCat.getBaseTypesAndSelf() // ["Cat","Animal","Class"]
dynamicCat.getFullName() // tab: fat cat
source code available at: Class.js
I also have more details in my blog post about OOP in javascript
Just thought I'd mention some of the issues with the classical pattern you're going for:
Reference vars on the super class(es) will be available as essentially statics on ALL instances. For example, if you have var arr = [1,2,3] in the super, and do instance_1.arr.push(4) instance_2.arr.push(5) ALL of these instances will "see" the changes.
So you solve 1. with Ayman's solution which Zakas calls "Constructor Stealing", but now you call the constructor twice: once for your prototype and once for the constructor stealing. Solution - for your prototype use a helper like inheritPrototype (I showed the whole implementation of this in this post: inheritPrototype method FWIW, this essentially came from a combination of page 181 of Zakas's book and some Crockford study.
No privacy (but then again, you'd need to use something like the Durable Object pattern to get this and that may not be what you want)
Object definition is left "dangling": Solution - put an if statement checking for any of your prototype's functions and then define the prototype with a prototype literal.
I have running examples of all of this on github!!!
It's been just as much of a challenge for me to truly grok both: Zakas and Crockford books on object creation and inheritance. I also needed to try some different JavaScript TDD frameworks. So I decided to create an essay on both TDD Frameworks and JavaScript Object Creation & Inheritance. It has running code and jspec tests! Here's the link:*
My GitHub Open Source Essay/Book

Categories

Resources