Related
Why this question is not a duplicate
This answer javascript inheritance from multiple objects does not solve my problem (although it has been marked as a duplicate of my previous question), because it is not scalable as it violates the DRY principle.
For this to work, one would have to manually reference each method like this :
Foo2.prototype.a = function() { /*code...*/};
Foo2.prototype.b = function() { /*code...*/};
Foo2.prototype.c = function() { /*code...*/};
Foo2.prototype.d = function() { /*code...*/};
//and so on and so on...
And what if I have dozens of classes containing dozens of methods ? Should I really manually copy-paste the same reference for each and every class over and over again in my source code ? While this solution would work for a very low number of classes, it is just not usable in a large-scale application using dozens or hundreds of classes.
The problem I'm trying to solve
I'm trying to instantiate objects which must inherit all the properties and methods of Animal and Flying_object using new keyword.
var objA = new Fish(),
objB = new Bird(),
objC = new UFO();
Tricky part is Animal and Flying_object can NOT have a parent-child relationship.
I know JavaScript doesn't implement native methods for multi-inheritance, so I'm posting this question to get some help finding a custom, scalable solution to this problem.
Code example and expected behavior
var Living_being = function() { this.className = 'Living_being'; };
var Animal = function() {
this.className = 'Animal';
this.vector = {x: 0, y: 0};
}
Animal.prototype = new Living_being();
Animal.prototype.getClassName = function() { console.log('Instance of... '+ this.className); };
Animal.prototype.get_vector = function() { console.log(this.vector); }
var Flying_object = function() {
this.className = 'Flying_object';
this.value = 'some value';
}
Flying_object.prototype.getClassName = function() { console.log('Instance of... '+ this.className); };
Flying_object.prototype.get_val = function() { console.log(this.value); }
// So far so good...
var UFO = function() {};
UFO.protoype = new Flying_object(); //classical inheritance
var Fish = function() {};
Fish.protoype = new Animal(); //classical inheritance
// Now the tricky part: how to make Bird share all of the methods and properties of Animal and Flying_object ?
var Bird = function() {};
Bird.prototype = new ....(); //pseudocode where .... is a class containing all the properties of Animal and Flying_object
var instance = new Bird();
//expected result:
instance.getClassName();//--> Instance of...
instance.get_vector(); //--> {x: 0, y: 0}
instance.get_val(); //--> 'some value'
This is where I'm stuck. How can I make Bird inherit from BOTH Animal and Flying_object ?
Any insight would be greatly apprenciated.
Here is a working solution I came up with at some point and gave up because I though there might be a better solution.
#Mörre: I'm not sure this is what you advised me to do in the comments: is this what you called object composition ? Or am I going all wrong here ?
Demo: https://jsfiddle.net/Lau1989/4ba8yrc8/1/
function mix(classA, classB) {
var instanceA = new classA(),
instanceB = new classB();
for (var prop in instanceA) {
instanceB[prop] = instanceA[prop];
}
return instanceB;
}
var Bird = function() { this.className = 'Bird'; };
Bird.prototype = mix(Animal, Flying_object);
var instance = new Bird();
If you need inherit from few classes you can extend prototype Bird from Animal and Ufo using jquery function $.extend({});.
Example $.extend(Bird.prototype,Animal.prototype,UFO.prototype) or you can create custom extend function.If names properties or functions has same names , they will be rewrite.
I got this from documentation: Using Object.assign() extend only enumerable properties.The Object.assign() method only copies enumerable and own properties from a source object to a target object. It uses [[Get]] on the source and [[Set]] on the target, so it will invoke getters and setters. Therefore it assigns properties versus just copying or defining new properties. This may make it unsuitable for merging new properties into a prototype if the merge sources contain getters. For copying property definitions, including their enumerability, into prototypes Object.getOwnPropertyDescriptor() and Object.defineProperty() should be used instead.
JavaScript does not support the concept of multiple inheritance. It also does not implement syntax for mixin and/or trait based composition. But unlike the former, the latter can be achieved by e.g. function and delegation based mixin patterns.
Thus, one first needs to figure out which parts of a composable object system should build the 'is a' relationship and which parts are behavior ('can do' / 'has a') that might get reused by/at different parts/levels of the object system.
The OP already has done this work. The example code that will be provided below is just going to introduce different function based mixin patterns via providing implementations of some behaviors like withLivingBeingBasics and withFlyingAbility ... with the first mixin covering the OP's Living_being class and the second one covering Flying_object.
For better code reuse there are 2 additional mixins, withExposeClassName and withExposeVector that, for the reason of demonstration, compose into the withExposeClassNameAndVector mixin compound.
From this possible base setup, that follows the OP's example, one could continue with shaping the classes.
With the Animal class one is free of choosing where mixin composition shall take place. Following the provided original example, composition at class/prototype level is the better option instead of applying the behavior at construction/instantiation time from within the constructor.
After applying withExposeClassNameAndVector and withLivingBeingBasics to Animal.prototype, any animal instance via prototypal delegation is capable of being invoked at getClassName and getVector as well as at metabolize and reproduce. Thus, at this point, both mixin composition (explicit delegation via call to prototype) and inheritance (automatically running delegation via prototype chain) take place.
The Fish class is implemented easily. As with the OP's example one just follows a simplified inheritance pattern via Fish.prototype = new Animal;. In addition, as already featured with the Animal base class, a class' name gets assigned to its prototype object.
Bird repeats the base patterns of Fish with the exception of featuring its own vector property that now is three dimensional instead of the otherwise prototypal two dimensional one. And since a common bird is supposed to somehow feature flying behavior Bird.prototype has to acquire it from withFlyingAbility.
Following still the OP's example, Ufo also needs to have flying ability. And like a bird, an ufo too has to feature an own three dimensional vector property. Thus the property gets assigned at construction/instantiation time and all the needed behavior gets applied from withExposeClassNameAndVector and from withFlyingAbility to Ufo.prototype.
The provided approach intends to prove that ... the most atomar mixin implements exactly one behavior, ... mixins are not necessarily supposed to introduce state but a behavior might operate upon state, ... mixins can be composed from other mixins, ... they always get applied at object level, either to already existing objects or to the prototype object itself or at composition time from within a constructor function ...
var withLivingBeingBasics = (function () { // function based mixin
function metabolize() { // implement beahvior once.
console.log('every living being features some kind of metabolism.');
}
function reproduce() { // implement beahvior once.
console.log('every living being features some kind of reproduction.');
}
return function() {
this.metabolize = metabolize; // assign shared code.
this.reproduce = reproduce; //
}
}());
var withFlyingAbility = (function () {
function liftOffAerodynamically() {
this.vector.z = 5;
console.log('flying needs some kind of aerodynamic lift.');
}
function monitorAltitudeDifference() {
console.log('monitoring altitude difference : ', this.vector.z);
}
return function() {
this.liftOffAerodynamically = liftOffAerodynamically;
this.monitorAltitudeDifference = monitorAltitudeDifference;
}
}());
var withExposeVector = (function () {
function getVector() {
console.log('vector : ', this.vector);
}
return function() {
this.getVector = getVector;
}
}());
var withExposeClassName = (function () {
function getClassName() {
console.log('Instance of... ', this.className);
}
return function() {
this.getClassName = getClassName;
}
}());
var withExposeClassNameAndVector = function () { // mixin compound.
withExposeClassName.call(this);
withExposeVector.call(this);
}
function Animal() {
//withLivingBeingBasics.call(this); // mixing in for the given example is …
//this.className = 'Animal'; // … better at **class**/prototype level.
this.vector = {x: 0, y: 0};
}
// the many ways of augmenting the `prototype` ...
Object.assign(Animal.prototype, { className: 'Animal' });
//withExposeClassName.call(Animal.prototype);
//withExposeVector.call(Animal.prototype);
withExposeClassNameAndVector.call(Animal.prototype);
withLivingBeingBasics.call(Animal.prototype);
function Fish() {}
Fish.prototype = new Animal;
Object.assign(Fish.prototype, { className: 'Fish' });
function Bird() {
this.vector = {x: 0, y: 0, z: 0};
}
Bird.prototype = new Animal;
Object.assign(Bird.prototype, { className: 'Bird' });
withFlyingAbility.call(Bird.prototype);
function Ufo() {
this.vector = {x: 0, y: 0, z: 0};
}
Object.assign(Ufo.prototype, { className: 'Ufo' });
//withExposeClassName.call(Ufo.prototype);
//withExposeVector.call(Ufo.prototype);
withExposeClassNameAndVector.call(Ufo.prototype);
withFlyingAbility.call(Ufo.prototype);
var fish = new Fish;
var bird = new Bird;
var ufo = new Ufo;
console.log('(fish instanceof Animal) ? ', (fish instanceof Animal));
console.log('(fish instanceof Fish) ? ', (fish instanceof Fish));
fish.getClassName();
fish.metabolize();
fish.reproduce();
fish.getVector();
console.log('(bird instanceof Animal) ? ', (bird instanceof Animal));
console.log('(bird instanceof Bird) ? ', (bird instanceof Bird));
bird.getClassName();
bird.metabolize();
bird.reproduce();
bird.getVector();
bird.monitorAltitudeDifference();
bird.liftOffAerodynamically();
bird.monitorAltitudeDifference();
console.log('(ufo instanceof Ufo) ? ', (ufo instanceof Ufo));
ufo.getClassName();
ufo.getVector();
ufo.monitorAltitudeDifference();
ufo.liftOffAerodynamically();
ufo.monitorAltitudeDifference();
.as-console-wrapper { max-height: 100%!important; top: 0; }
For further reading on SO one might give the following related questions and solutions a chance ...
What are the practical differences between Mixins and Inheritance in Javascript?
Mixins for ES6 classes, transpiled with babel
Traits in javascript
Accessors Composition in ES6 Classes
I'm reading this article about perils of trying to mimic OOP in JavaScript and there's the following:
In JavaScript, factory functions are simply constructor functions
minus the new requirement, global pollution danger and awkward
limitations (including that annoying initial capitalized letter
convention).
JavaScript doesn’t need constructor functions because any
function can return a new object. With dynamic object extension,
object literals and Object.create(), we have everything we
need — with none of the mess. And this behaves just like it does in
any other function. Hurray!
Am I right to assume that given this approach we should replace this code:
function Rabbit() {
this.speed = 3;
}
Rabbit.prototype = {
this.getSpeed = function() {
return this.speed;
}
}
var rabbit = new Rabbit();
With this:
function RabbitFactory() {
var rabbit = {
speed: 3
};
Object.setPrototypeOf(rabbit, {
getSpeed: function() {
return this.speed;
}
})
return rabbit;
}
var rabbit = RabbitFactory();
Basically I would distinguish 3 approaches to create an object in JS:
Class
Constructor
Factory
Here are 3 examples (considering your Rabbit's one)
// class
class Rabbit {
constructor() {
this.speed = 3;
// it would be so nice to have just 'static const speed = 3;' instead of
// using constructor for that
}
getSpeed() {
return this.speed;
}
}
let rabbit1 = new Rabbit();
// constructor
function ConstructorRabbit(){ }
ConstructorRabbit.prototype.speed = 3;
ConstructorRabbit.prototype.getSpeed = function() {
return this.speed;
};
let rabbit2 = new ConstructorRabbit();
// factory
const rabbitProto = {
speed: 3,
getSpeed() {
return this.speed;
}
};
function factoryRabbit () {
return Object.create(rabbitProto);
}
let rabbit3 = factoryRabbit();
I'm not sure that there are so many pros to use only factory for creating objects, but probably I can single out the one. As mentioned in the article if we refer to very famous 'Design Patterns', so we should prefer object composition instead of class inheritance. And I'm totally agree with that postulate, thus returning back to JS and ES6 classes, we can say that prototype delegation may be better than class inheritance in some cases.
But also, we shouldn't forget this (as mentioned in the article as well) statement: "How it’s implemented doesn’t matter at all unless it’s implemented poorly". And this one, I would say, is a really good one.
Many answers here suggest Constructor Functions, although the name of the questions has to do with Factory Functions.
Factory Functions look like the following:
const RabbitFactory = () => {
const speed = 3;
const GetSpeed = () => speed;
return { GetSpeed }
}
const rabbit = RabbitFactory();
rabbit.GetSpeed() // -> 3
rabbit.speed // -> undefined!
I like Factory functions more than Constructor function because:
You don't need to get messy with prototyping
You don't need to use the Object constructor
Gives you the ability to choose what is private and what is public in your factory
(in my example, speed is private and this is a good practice. If you want to read the value of rabbit's speed, use the GetSpeed getter)
No, that is wrong. You should not use Object.setPrototypeOf, better use Object.create (though it makes no difference for the result). And if you create the prototype from an object literal every time, it loses all of its sharing advantages, so you should either drop that completely or move it outside the function to make it static. The correct™ way to write the factory function would be
const protoRabbit = {
getSpeed: function() {
return this.speed;
}
};
function createRabbit() {
var rabbit = Object.create(protoRabbit);
rabbit.speed = 3;
return rabbit;
}
var rabbit = createRabbit();
I don't like these answers because they use the this keyword. You can avoid this altogether and still use a factory function like this:
function createRabbit() {
var speed = 3;
return {
getSpeed: function() {
return speed;
}
}
}
var rabbit = createRabbit();
console.log(rabbit.getSpeed());
This guy has a good article about it: http://radar.oreilly.com/2014/03/javascript-without-the-this.html
The simplest pattern is:
function RabbitFactory() {
return {
speed: 3,
getSpeed() { return this.speed; }
};
}
var rabbit = RabbitFactory();
This text awfully sounds like a Douglas Crockford speech. Anyway it mentions this pattern.
function RabbitFactory(){
rabbit = Object.create({ getSpeed: function() {
return this.speed;
}
});
rabbit.speed = 3;
return rabbit;
}
setPrototypeOf/getPrototypeOf or the __proto__ property are introduced in ES6 whereas Object.create() is an ES5 functionality. setPrototypeOf/getPrototypeOf or the __proto__ are good for subclassing thingies but you shouldn't use it together with Object.create()
I would keep using constructor functions though.
I typically implement inheritance along the following lines.
function Animal () { this.x = 0; this.y = 0;}
Animal.prototype.locate = function() {
console.log(this.x, this.y);
return this;
};
Animal.prototype.move = function(x, y) {
this.x = this.x + x;
this.y = this.y + y;
return this;
}
function Duck () {
Animal.call(this);
}
Duck.prototype = new Animal();
Duck.prototype.constructor = Duck;
Duck.prototype.speak = function () {
console.log("quack");
return this;
}
var daffy = new Duck();
daffy.move(6, 7).locate().speak();
I've read this post by Eric Elliott and if I understand correctly I can use Object.create and Object.assign instead? Is it really that simple?
var animal = {
x : 0,
y : 0,
locate : function () {
console.log(this.x, this.y);
return this;
},
move : function (x, y) {
this.x = this.x + x;
this.y = this.y + y;
return this;
}
}
var duck = function () {
return Object.assign(Object.create(animal), {
speak : function () {
console.log("quack");
return this;
}
});
}
var daffy = duck();
daffy.move(6, 7).locate().speak();
As an aside, by convention constructor functions are capitalized, should object literals that act as constructors also be capitalized?
I realise there are many questions here discussing new versus Object.create, but they typically seem to relate to Duck.prototype = new Animal(); versus Duck.prototype = Object.create(Animal.prototype);
Yes, it is that simple. In your example with Object.create/Object.assign, you are using a factory function to create new instances of duck (similar to the way jQuery creates new instances if you select an element with var body = $('body')). An advantage of this code style is, that it doesn't force you to call a constructor of animal when you want to create a new duck instance (as opposed to ES2015 Classes).
Differences in initialization
Maybe one interesting tidbit that works slightly differently than if you were to use a constructor (or any other initialization function):
When you create a duck instace, all the properties of animal are in the [[Prototype]] slot of the duck instance.
var daffy = duck();
console.log(daffy); // Object { speak: function() }
So daffy does not have any own x and y properties yet. However, when you call the following, they will be added:
daffy.move(6, 7);
console.log(daffy); // Object { speak: function(), x: 6, y: 7 }
Why? In the function-body of animal.move, we have the following statement:
this.x = this.x + x;
So when you call this with daffy.move, this refers to daffy. So it will try to assign this.x + x to this.x. Since this.x is not yet defined, the [[Prototype]] chain of daffy is traversed down to animal, where animal.x is defined.
Thus in the first call, the this.x on the right side of the assignment refers to animal.x, because daffy.x is not defined. The second time daffy.move(1,2) is called, this.x on the right side will be daffy.x.
Alternative Syntax
Alternatively, you could also use Object.setPrototypeOf instead of Object.create/Object.assign (OLOO Style):
var duck = function () {
var duckObject = {
speak : function () {
console.log("quack");
return this;
}
};
return Object.setPrototypeOf(duckObject, animal);
}
Naming Conventions
I'm not aware of any established conventions. Kyle Simpson uses uppercase letters in OLOO, Eric Elliot seems to use lowercase. Personally I would stick with lower-case, because the object literals that act as constructors are already fully fledged objects themselves (not just blueprint, like classes would be).
Singleton
If you only wanted a single instance (e.g. for a singleton), you could just call it directly:
var duck = Object.assign(Object.create(animal), {
speak : function () {
console.log("quack");
return this;
}
});
duck.move(6, 7).locate().speak();
I've read this post by Eric Elliott and if I understand correctly I can use Object.create and Object.assign instead? Is it really that simple?
Yes, create and assign is much more simple because they're primitives, and less magic is going on - everything you do is explicit.
However, Eric's mouse example is a bit confusing, as he leaves out one step, and mixes the inheritance of mouses from animals with instantiating mouses.
Rather let's try transcribing your duckling example again - let's start with doing it literally:
const animal = {
constructor() {
this.x = 0;
this.y = 0;
return this;
},
locate() {
console.log(this.x, this.y);
return this;
},
move(x, y) {
this.x += x;
this.y += y;
return this;
}
};
const duck = Object.assign(Object.create(animal), {
constructor() {
return animal.constructor.call(this);
},
speak() {
console.log("quack");
return this;
}
});
/* alternatively:
const duck = Object.setPrototypeOf({
constructor() {
return super.constructor(); // super doesn't work with `Object.assign`
},
speak() { … }
}, animal); */
let daffy = Object.create(duck).constructor();
daffy.move(6, 7).locate().speak();
You should see that what happens here is really no different from using constructors (or class syntax for that matter), we've just stored our prototypes directly in the variables and we're doing instantiation with an explicit call to create and constructor.
Now you can figure that our duck.constructor does nothing but calling its super method, so we can actually omit it completely and let inheritance do its work:
const duck = Object.assign(Object.create(animal), {
speak() {
console.log("quack");
return this;
}
});
The other thing that is often changed is the initialisation of instance properties. There is actually no reason to initialise them if we don't really need them, it's sufficient to put some default values on the prototype:
const animal = {
x: 0,
y: 0,
locate() {
console.log(this.x, this.y);
}
};
const duck = … Object.create(animal) …;
let daffy = Object.create(duck); // no constructor call any more!
daffy.x = 5; // instance initialisation by explicit assignment
daffy.locate();
The problem with this is that it only works for primitive values, and it gets repetitive. This is where factory functions get in:
function makeDuck(x, y) {
return Object.assign(Object.create(duck), {x, y});
}
let daffy = makeDuck(5, 0);
To allow for easy inheritance, the initialisation is often not done in the factory but in a dedicated method so it can be called on "subclass" instances as well. You may call this method init, or you may call it constructor like I did above, it's basically the same.
As an aside, by convention constructor functions are capitalized, should object literals that act as constructors also be capitalized?
If you're not using any constructors, you may assign a new meaning to capitalized variable names, yes. It might however be confusing for everyone who's not accustomed to this. And btw, they're not "object literals that act as constructors", they're just prototype objects.
Rather than "inheritance" you should think about what type of "instantiation pattern" you intend to use. They have different purposes for implementation.
The top example is prototypal and the bottom, functional-shared. Check out this link: JS Instantiation patterns
Also, this is non-es6 related.
I am involved in a web application project at the moment and we are not going to be using a framework.
I am looking for the 'best' javascript inheritance implementation. I have worked with prototypal style classes as follows:
function animal(options) {
self = this;
//properties
this.name = options.name;
//events
this.onXYZ = options.onXYZ;
//event handlers
this.handlerOfEvent = function() {
//do something using 'self' as the 'this' variable
}
}
animal.prototype.aFunction = function()
{
//do something
}
etc.
I have not used inheritance without a framework (usually use Mootools) but I do understand to a point how it works in Javascript and have seen a fair few implementations.
I wanted to get some feedback on where I could find the best implementation, one that doesn't fiddle with any native types and allows me full access to the ascendant classes' properties and functions.
Any pointers would be greatly appreciated.
Thanks very much for your time.
There's a method described by (who else) Douglas Crockford that I've been partial to as of late:
var rectangle = function(width, height)
{
var h = height, w = width;
var scale = function(s)
{
h = h * s;
w = w * s;
}
return { scale: scale };
}
var square = function(width)
{
var o = rectangle(width, width)
// Add things to o, if needed
return o;
}
Not a terribly good example, as nothing is really being extended, but it should get the idea across. In order to instantiate these objects, simply use this:
var newRectangle = rectangle(3, 4); // 3 by 4 rectangle
var newSquare = square(6); // 6 by 6 square
I tried many approaches in the past. I like John Resig way of implementation the most. It's very simple. You can see full example and javascript file (only around 25 lines of code) from http://ejohn.org/blog/simple-javascript-inheritance/
Just to complete the answer, you can implement a class like this after include his code..
var Person = Class.extend({
name : '',
init : function (name) {
this.name = name;
},
say : function () {
alert("I'm " + this.name);
}
});
var mick = new Person("Mick");
mick.say();
Take a look at Simple Javascript Class Project (constant, property, protected, static, utils, and more), Simple JavaScript Inheritance and Inheritance Patterns in JavaScript.
Simple Javascript Class (sjsClass) Example
Class.extend('Foo', {
__protected : {
privV : 123,
privF : function () {
return this.privV + this.priv3;
}
},
'protected priv3' : 'Protected Value',
setX : function (x) {
this.privV = x;
},
test : function () { return this.privF(); }
});
var f = new Foo;
f.setX(456);
f.test(); // -> 'Protected Value456'
f.privF(); // -> Error
f.privV; // -> undefined
f.priv3; // -> undefined
You should check the videos from Douglas Crockford about "parasatic inheritance".
Here's a basic example
var pkg={};//simulating a package
pkg.ObjA=function (){
var privateField;//every inner function will have a closure to this field, this is the way to simulate private fields
var privatefunc=function(){
//same for private functions
};
//use object augmentation to add different fields to the "that" reference
that.publicMethod=function(){
//do something
};
return that;
}
//create two different instance of the object A
var instance1=pkg.ObjA();
var instance2=pkg.ObjA();
pkg.ObjB=function(){
//the that of this object is based on the ObjA
var that=pkg.ObjA();
//specialize the that to simulate inheritance
that.newMethod=function(){
}
return that;
}
var child=pkg.ObjB();
I wonder about what the best way is to create an JavaScript object that has properties and methods.
I have seen examples where the person used var self = this and then uses self. in all functions to make sure the scope is always correct.
Then I have seen examples of using .prototype to add properties, while others do it inline.
Can someone give me a proper example of a JavaScript object with some properties and methods?
There are two models for implementing classes and instances in JavaScript: the prototyping way, and the closure way. Both have advantages and drawbacks, and there are plenty of extended variations. Many programmers and libraries have different approaches and class-handling utility functions to paper over some of the uglier parts of the language.
The result is that in mixed company you will have a mishmash of metaclasses, all behaving slightly differently. What's worse, most JavaScript tutorial material is terrible and serves up some kind of in-between compromise to cover all bases, leaving you very confused. (Probably the author is also confused. JavaScript's object model is very different to most programming languages, and in many places straight-up badly designed.)
Let's start with the prototype way. This is the most JavaScript-native you can get: there is a minimum of overhead code and instanceof will work with instances of this kind of object.
function Shape(x, y) {
this.x= x;
this.y= y;
}
We can add methods to the instance created by new Shape by writing them to the prototype lookup of this constructor function:
Shape.prototype.toString= function() {
return 'Shape at '+this.x+', '+this.y;
};
Now to subclass it, in as much as you can call what JavaScript does subclassing. We do that by completely replacing that weird magic prototype property:
function Circle(x, y, r) {
Shape.call(this, x, y); // invoke the base class's constructor function to take co-ords
this.r= r;
}
Circle.prototype= new Shape();
before adding methods to it:
Circle.prototype.toString= function() {
return 'Circular '+Shape.prototype.toString.call(this)+' with radius '+this.r;
}
This example will work and you will see code like it in many tutorials. But man, that new Shape() is ugly: we're instantiating the base class even though no actual Shape is to be created. It happens to work in this simple case because JavaScript is so sloppy: it allows zero arguments to be passed in, in which case x and y become undefined and are assigned to the prototype's this.x and this.y. If the constructor function were doing anything more complicated, it would fall flat on its face.
So what we need to do is find a way to create a prototype object which contains the methods and other members we want at a class level, without calling the base class's constructor function. To do this we are going to have to start writing helper code. This is the simplest approach I know of:
function subclassOf(base) {
_subclassOf.prototype= base.prototype;
return new _subclassOf();
}
function _subclassOf() {};
This transfers the base class's members in its prototype to a new constructor function which does nothing, then uses that constructor. Now we can write simply:
function Circle(x, y, r) {
Shape.call(this, x, y);
this.r= r;
}
Circle.prototype= subclassOf(Shape);
instead of the new Shape() wrongness. We now have an acceptable set of primitives to built classes.
There are a few refinements and extensions we can consider under this model. For example here is a syntactical-sugar version:
Function.prototype.subclass= function(base) {
var c= Function.prototype.subclass.nonconstructor;
c.prototype= base.prototype;
this.prototype= new c();
};
Function.prototype.subclass.nonconstructor= function() {};
...
function Circle(x, y, r) {
Shape.call(this, x, y);
this.r= r;
}
Circle.subclass(Shape);
Either version has the drawback that the constructor function cannot be inherited, as it is in many languages. So even if your subclass adds nothing to the construction process, it must remember to call the base constructor with whatever arguments the base wanted. This can be slightly automated using apply, but still you have to write out:
function Point() {
Shape.apply(this, arguments);
}
Point.subclass(Shape);
So a common extension is to break out the initialisation stuff into its own function rather than the constructor itself. This function can then inherit from the base just fine:
function Shape() { this._init.apply(this, arguments); }
Shape.prototype._init= function(x, y) {
this.x= x;
this.y= y;
};
function Point() { this._init.apply(this, arguments); }
Point.subclass(Shape);
// no need to write new initialiser for Point!
Now we've just got the same constructor function boilerplate for each class. Maybe we can move that out into its own helper function so we don't have to keep typing it, for example instead of Function.prototype.subclass, turning it round and letting the base class's Function spit out subclasses:
Function.prototype.makeSubclass= function() {
function Class() {
if ('_init' in this)
this._init.apply(this, arguments);
}
Function.prototype.makeSubclass.nonconstructor.prototype= this.prototype;
Class.prototype= new Function.prototype.makeSubclass.nonconstructor();
return Class;
};
Function.prototype.makeSubclass.nonconstructor= function() {};
...
Shape= Object.makeSubclass();
Shape.prototype._init= function(x, y) {
this.x= x;
this.y= y;
};
Point= Shape.makeSubclass();
Circle= Shape.makeSubclass();
Circle.prototype._init= function(x, y, r) {
Shape.prototype._init.call(this, x, y);
this.r= r;
};
...which is starting to look a bit more like other languages, albeit with slightly clumsier syntax. You can sprinkle in a few extra features if you like. Maybe you want makeSubclass to take and remember a class name and provide a default toString using it. Maybe you want to make the constructor detect when it has accidentally been called without the new operator (which would otherwise often result in very annoying debugging):
Function.prototype.makeSubclass= function() {
function Class() {
if (!(this instanceof Class))
throw('Constructor called without "new"');
...
Maybe you want to pass in all the new members and have makeSubclass add them to the prototype, to save you having to write Class.prototype... quite so much. A lot of class systems do that, eg:
Circle= Shape.makeSubclass({
_init: function(x, y, z) {
Shape.prototype._init.call(this, x, y);
this.r= r;
},
...
});
There are a lot of potential features you might consider desirable in an object system and no-one really agrees on one particular formula.
The closure way, then. This avoids the problems of JavaScript's prototype-based inheritance, by not using inheritance at all. Instead:
function Shape(x, y) {
var that= this;
this.x= x;
this.y= y;
this.toString= function() {
return 'Shape at '+that.x+', '+that.y;
};
}
function Circle(x, y, r) {
var that= this;
Shape.call(this, x, y);
this.r= r;
var _baseToString= this.toString;
this.toString= function() {
return 'Circular '+_baseToString(that)+' with radius '+that.r;
};
};
var mycircle= new Circle();
Now every single instance of Shape will have its own copy of the toString method (and any other methods or other class members we add).
The bad thing about every instance having its own copy of each class member is that it's less efficient. If you are dealing with large numbers of subclassed instances, prototypical inheritance may serve you better. Also calling a method of the base class is slightly annoying as you can see: we have to remember what the method was before the subclass constructor overwrote it, or it gets lost.
[Also because there is no inheritance here, the instanceof operator won't work; you would have to provide your own mechanism for class-sniffing if you need it. Whilst you could fiddle the prototype objects in a similar way as with prototype inheritance, it's a bit tricky and not really worth it just to get instanceof working.]
The good thing about every instance having its own method is that the method may then be bound to the specific instance that owns it. This is useful because of JavaScript's weird way of binding this in method calls, which has the upshot that if you detach a method from its owner:
var ts= mycircle.toString;
alert(ts());
then this inside the method won't be the Circle instance as expected (it'll actually be the global window object, causing widespread debugging woe). In reality this typically happens when a method is taken and assigned to a setTimeout, onclick or EventListener in general.
With the prototype way, you have to include a closure for every such assignment:
setTimeout(function() {
mycircle.move(1, 1);
}, 1000);
or, in the future (or now if you hack Function.prototype) you can also do it with function.bind():
setTimeout(mycircle.move.bind(mycircle, 1, 1), 1000);
if your instances are done the closure way, the binding is done for free by the closure over the instance variable (usually called that or self, though personally I would advise against the latter as self already has another, different meaning in JavaScript). You don't get the arguments 1, 1 in the above snippet for free though, so you would still need another closure or a bind() if you need to do that.
There are lots of variants on the closure method too. You may prefer to omit this completely, creating a new that and returning it instead of using the new operator:
function Shape(x, y) {
var that= {};
that.x= x;
that.y= y;
that.toString= function() {
return 'Shape at '+that.x+', '+that.y;
};
return that;
}
function Circle(x, y, r) {
var that= Shape(x, y);
that.r= r;
var _baseToString= that.toString;
that.toString= function() {
return 'Circular '+_baseToString(that)+' with radius '+r;
};
return that;
};
var mycircle= Circle(); // you can include `new` if you want but it won't do anything
Which way is “proper”? Both. Which is “best”? That depends on your situation. FWIW I tend towards prototyping for real JavaScript inheritance when I'm doing strongly OO stuff, and closures for simple throwaway page effects.
But both ways are quite counter-intuitive to most programmers. Both have many potential messy variations. You will meet both (as well as many in-between and generally broken schemes) if you use other people's code/libraries. There is no one generally-accepted answer. Welcome to the wonderful world of JavaScript objects.
[This has been part 94 of Why JavaScript Is Not My Favourite Programming Language.]
I use this pattern fairly frequently - I've found that it gives me a pretty huge amount of flexibility when I need it. In use it's rather similar to Java-style classes.
var Foo = function()
{
var privateStaticMethod = function() {};
var privateStaticVariable = "foo";
var constructor = function Foo(foo, bar)
{
var privateMethod = function() {};
this.publicMethod = function() {};
};
constructor.publicStaticMethod = function() {};
return constructor;
}();
This uses an anonymous function that is called upon creation, returning a new constructor function. Because the anonymous function is called only once, you can create private static variables in it (they're inside the closure, visible to the other members of the class). The constructor function is basically a standard Javascript object - you define private attributes inside of it, and public attributes are attached to the this variable.
Basically, this approach combines the Crockfordian approach with standard Javascript objects to create a more powerful class.
You can use it just like you would any other Javascript object:
Foo.publicStaticMethod(); //calling a static method
var test = new Foo(); //instantiation
test.publicMethod(); //calling a method
Douglas Crockford discusses that topic extensively in The Good Parts. He recommends to avoid the new operator to create new objects. Instead he proposes to create customized constructors. For instance:
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'});
In Javascript a function is an object, and can be used to construct objects out of together with the new operator. By convention, functions intended to be used as constructors start with a capital letter. You often see things like:
function Person() {
this.name = "John";
return this;
}
var person = new Person();
alert("name: " + person.name);**
In case you forget to use the new operator while instantiating a new object, what you get is an ordinary function call, and this is bound to the global object instead to the new object.
To continue off of bobince's answer
In es6 you can now actually create a class
So now you can do:
class Shape {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return `Shape at ${this.x}, ${this.y}`;
}
}
So extend to a circle (as in the other answer) you can do:
class Circle extends Shape {
constructor(x, y, r) {
super(x, y);
this.r = r;
}
toString() {
let shapeString = super.toString();
return `Circular ${shapeString} with radius ${this.r}`;
}
}
Ends up a bit cleaner in es6 and a little easier to read.
Here is a good example of it in action:
class Shape {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return `Shape at ${this.x}, ${this.y}`;
}
}
class Circle extends Shape {
constructor(x, y, r) {
super(x, y);
this.r = r;
}
toString() {
let shapeString = super.toString();
return `Circular ${shapeString} with radius ${this.r}`;
}
}
let c = new Circle(1, 2, 4);
console.log('' + c, c);
You can also do it this way, using structures :
function createCounter () {
var count = 0;
return {
increaseBy: function(nb) {
count += nb;
},
reset: function {
count = 0;
}
}
}
Then :
var counter1 = createCounter();
counter1.increaseBy(4);
Another way would be http://jsfiddle.net/nnUY4/
(i dont know if this kind of handling object creation and revealing functions follow any specific pattern)
// Build-Reveal
var person={
create:function(_name){ // 'constructor'
// prevents direct instantiation
// but no inheritance
return (function() {
var name=_name||"defaultname"; // private variable
// [some private functions]
function getName(){
return name;
}
function setName(_name){
name=_name;
}
return { // revealed functions
getName:getName,
setName:setName
}
})();
}
}
// … no (instantiated) person so far …
var p=person.create(); // name will be set to 'defaultname'
p.setName("adam"); // and overwritten
var p2=person.create("eva"); // or provide 'constructor parameters'
alert(p.getName()+":"+p2.getName()); // alerts "adam:eva"
Creating an object
The easiest way to create an object in JavaScript is to use the following syntax :
var test = {
a : 5,
b : 10,
f : function(c) {
return this.a + this.b + c;
}
}
console.log(test);
console.log(test.f(3));
This works great for storing data in a structured way.
For more complex use cases, however, it's often better to create instances of functions :
function Test(a, b) {
this.a = a;
this.b = b;
this.f = function(c) {
return this.a + this.b + c;
};
}
var test = new Test(5, 10);
console.log(test);
console.log(test.f(3));
This allows you to create multiple objects that share the same "blueprint", similar to how you use classes in eg. Java.
This can still be done more efficiently, however, by using a prototype.
Whenever different instances of a function share the same methods or properties, you can move them to that object's prototype. That way, every instance of a function has access to that method or property, but it doesn't need to be duplicated for every instance.
In our case, it makes sense to move the method f to the prototype :
function Test(a, b) {
this.a = a;
this.b = b;
}
Test.prototype.f = function(c) {
return this.a + this.b + c;
};
var test = new Test(5, 10);
console.log(test);
console.log(test.f(3));
Inheritance
A simple but effective way to do inheritance in JavaScript, is to use the following two-liner :
B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;
That is similar to doing this :
B.prototype = new A();
The main difference between both is that the constructor of A is not run when using Object.create, which is more intuitive and more similar to class based inheritance.
You can always choose to optionally run the constructor of A when creating a new instance of B by adding adding it to the constructor of B :
function B(arg1, arg2) {
A(arg1, arg2); // This is optional
}
If you want to pass all arguments of B to A, you can also use Function.prototype.apply() :
function B() {
A.apply(this, arguments); // This is optional
}
If you want to mixin another object into the constructor chain of B, you can combine Object.create with Object.assign :
B.prototype = Object.assign(Object.create(A.prototype), mixin.prototype);
B.prototype.constructor = B;
Demo
function A(name) {
this.name = name;
}
A.prototype = Object.create(Object.prototype);
A.prototype.constructor = A;
function B() {
A.apply(this, arguments);
this.street = "Downing Street 10";
}
B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;
function mixin() {
}
mixin.prototype = Object.create(Object.prototype);
mixin.prototype.constructor = mixin;
mixin.prototype.getProperties = function() {
return {
name: this.name,
address: this.street,
year: this.year
};
};
function C() {
B.apply(this, arguments);
this.year = "2018"
}
C.prototype = Object.assign(Object.create(B.prototype), mixin.prototype);
C.prototype.constructor = C;
var instance = new C("Frank");
console.log(instance);
console.log(instance.getProperties());
Note
Object.create can be safely used in every modern browser, including IE9+. Object.assign does not work in any version of IE nor some mobile browsers. It is recommended to polyfill Object.create and/or Object.assign if you want to use them and support browsers that do not implement them.
You can find a polyfill for Object.create here
and one for Object.assign here.
When one uses the trick of closing on "this" during a constructor invocation, it's in order to write a function that can be used as a callback by some other object that doesn't want to invoke a method on an object. It's not related to "making the scope correct".
Here's a vanilla JavaScript object:
function MyThing(aParam) {
var myPrivateVariable = "squizzitch";
this.someProperty = aParam;
this.useMeAsACallback = function() {
console.log("Look, I have access to " + myPrivateVariable + "!");
}
}
// Every MyThing will get this method for free:
MyThing.prototype.someMethod = function() {
console.log(this.someProperty);
};
You might get a lot out of reading what Douglas Crockford has to say about JavaScript. John Resig is also brilliant. Good luck!
Closure is versatile. bobince has well summarized the prototype vs. closure approaches when creating objects. However you can mimic some aspects of OOP using closure in a functional programming way. Remember functions are objects in JavaScript; so use function as object in a different way.
Here is an example of closure:
function outer(outerArg) {
return inner(innerArg) {
return innerArg + outerArg; //the scope chain is composed of innerArg and outerArg from the outer context
}
}
A while ago I came across the Mozilla's article on Closure. Here is what jump at my eyes: "A closure lets you associate some data (the environment) with a function that operates on that data. This has obvious parallels to object oriented programming, where objects allow us to associate some data (the object's properties) with one or more methods". It was the very first time I read a parallelism between closure and classic OOP with no reference to prototype.
How?
Suppose you want to calculate the VAT of some items. The VAT is likely to stay stable during the lifetime of an application. One way to do it in OOP (pseudo code):
public class Calculator {
public property VAT { get; private set; }
public Calculator(int vat) {
this.VAT = vat;
}
public int Calculate(int price) {
return price * this.VAT;
}
}
Basically you pass a VAT value into your constructor and your calculate method can operate upon it via closure.
Now instead of using a class/constructor, pass your VAT as an argument into a function. Because the only stuff you are interested in is the calculation itself, returns a new function, which is the calculate method:
function calculator(vat) {
return function(item) {
return item * vat;
}
}
var calculate = calculator(1.10);
var jsBook = 100; //100$
calculate(jsBook); //110
In your project identify top-level values that are good candidate of what VAT is for calculation. As a rule of thumb whenever you pass the same arguments on and on, there is a way to improve it using closure. No need to create traditional objects.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures
A Pattern That Serves Me Well
var Klass = function Klass() {
var thus = this;
var somePublicVariable = x
, somePublicVariable2 = x
;
var somePrivateVariable = x
, somePrivateVariable2 = x
;
var privateMethod = (function p() {...}).bind(this);
function publicMethod() {...}
// export precepts
this.var1 = somePublicVariable;
this.method = publicMethod;
return this;
};
First, you may change your preference of adding methods to the instance instead of the constructor's prototype object. I almost always declare methods inside of the constructor because I use Constructor Hijacking very often for purposes regarding Inheritance & Decorators.
Here's how I decide where which declarations are writ:
Never declare a method directly on the context object (this)
Let var declarations take precedence over function declarations
Let primitives take precedence over objects ({} and [])
Let public declarations take precedence over private declarations
Prefer Function.prototype.bind over thus, self, vm, etc
Avoid declaring a Class within another Class, unless:
It should be obvious that the two are inseparable
The Inner class implements The Command Pattern
The Inner class implements The Singleton Pattern
The Inner class implements The State Pattern
The Inner Class implements another Design Pattern that warrants this
Always return this from within the Lexical Scope of the Closure Space.
Here's why these help:
Constructor Hijacking
var Super = function Super() {
...
this.inherited = true;
...
};
var Klass = function Klass() {
...
// export precepts
Super.apply(this); // extends this with property `inherited`
...
};
Model Design
var Model = function Model(options) {
var options = options || {};
this.id = options.id || this.id || -1;
this.string = options.string || this.string || "";
// ...
return this;
};
var model = new Model({...});
var updated = Model.call(model, { string: 'modified' });
(model === updated === true); // > true
Design Patterns
var Singleton = new (function Singleton() {
var INSTANCE = null;
return function Klass() {
...
// export precepts
...
if (!INSTANCE) INSTANCE = this;
return INSTANCE;
};
})();
var a = new Singleton();
var b = new Singleton();
(a === b === true); // > true
As you can see, I really have no need for thus since I prefer Function.prototype.bind (or .call or .apply) over thus. In our Singleton class, we don't even name it thus because INSTANCE conveys more information. For Model, we return this so that we can invoke the Constructor using .call to return the instance we passed into it. Redundantly, we assigned it to the variable updated, though it is useful in other scenarios.
Alongside, I prefer constructing object-literals using the new keyword over {brackets}:
Preferred
var klass = new (function Klass(Base) {
...
// export precepts
Base.apply(this); //
this.override = x;
...
})(Super);
Not Preferred
var klass = Super.apply({
override: x
});
As you can see, the latter has no ability to override its Superclass's "override" property.
If I do add methods to the Class's prototype object, I prefer an object literal -- with or without using the new keyword:
Preferred
Klass.prototype = new Super();
// OR
Klass.prototype = new (function Base() {
...
// export precepts
Base.apply(this);
...
})(Super);
// OR
Klass.prototype = Super.apply({...});
// OR
Klass.prototype = {
method: function m() {...}
};
Not Preferred
Klass.prototype.method = function m() {...};
I'd like to mention that we can use either a Title or a String to declare an Object.
There are different ways on calling each type of them. See below:
var test = {
useTitle : "Here we use 'a Title' to declare an Object",
'useString': "Here we use 'a String' to declare an Object",
onTitle : function() {
return this.useTitle;
},
onString : function(type) {
return this[type];
}
}
console.log(test.onTitle());
console.log(test.onString('useString'));
var Person = function (lastname, age, job){
this.name = name;
this.age = age;
this.job = job;
this.changeName = function(name){
this.lastname = name;
}
}
var myWorker = new Person('Adeola', 23, 'Web Developer');
myWorker.changeName('Timmy');
console.log("New Worker" + myWorker.lastname);
In addition to the accepted answer from 2009. If you can can target modern browsers, one can make use of the Object.defineProperty.
The Object.defineProperty() method defines a new property directly on
an object, or modifies an existing property on an object, and returns
the object.
Source: Mozilla
var Foo = (function () {
function Foo() {
this._bar = false;
}
Object.defineProperty(Foo.prototype, "bar", {
get: function () {
return this._bar;
},
set: function (theBar) {
this._bar = theBar;
},
enumerable: true,
configurable: true
});
Foo.prototype.toTest = function () {
alert("my value is " + this.bar);
};
return Foo;
}());
// test instance
var test = new Foo();
test.bar = true;
test.toTest();
To see a desktop and mobile compatibility list, see Mozilla's Browser Compatibility list. Yes, IE9+ supports it as well as Safari mobile.
You can also try this
function Person(obj) {
'use strict';
if (typeof obj === "undefined") {
this.name = "Bob";
this.age = 32;
this.company = "Facebook";
} else {
this.name = obj.name;
this.age = obj.age;
this.company = obj.company;
}
}
Person.prototype.print = function () {
'use strict';
console.log("Name: " + this.name + " Age : " + this.age + " Company : " + this.company);
};
var p1 = new Person({name: "Alex", age: 23, company: "Google"});
p1.print();
Bascially there is no concept of class in JS so we use function as a class constructor which is relevant with the existing design patterns.
//Constructor Pattern
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.doSomething = function(){
alert('I am Happy');
}
}
Till now JS has no clue that you want to create an object so here comes the new keyword.
var person1 = new Person('Arv', 30, 'Software');
person1.name //Arv
Ref : Professional JS for web developers - Nik Z