What's the recommended way of creating objects in NodeJS? - javascript

I'm building a composite for request module, however I'm not sure what's the best practice regarding building objects in JS for Node.
Option 1:
function RequestComposite(request) {
return {
get: function (url) { return request.get(url); }
}
}
var comp = RequestComposite(request);
Note: I know that i should call a CB in async way, but for the ease of explaination I return it...
Option 2:
function RequestComposite(request) {
this.request = request;
}
RequestComposite.prototype.get = function (url) { return this.request.get(url); };
var comp = new RequestComposite(request);
Option 3:
var RequestComposite = {
init: function (request) { this.request = request; },
get: function (url) { return request.get(url); }
}
var comp = Object.create(RequestComposite).init(request);
I tried to find my way around, however I got even more confused about how should I use objects...
Would the answer be different if I want to use objects for browsers?
Thanks.

The most efficient way is the following:
Put all the essential initialisation in the constructor (e.g. validate constructor parameters, set properties, etc).
Set methods in the .prototype property of the constructor. Why? Because this prevents from re-writing each method each time you create an object. This way you recycle the same prototype for each object you create. Efficient in memory and sparing coding time.
Do not use closures for private properties. Why? It is slow, and prevents you from using this object in an inheritance chain (the pseudo-private vars don't belong to the object, they're just accessible). It is instead common practice to use an underscore when declaring an object property, to indicate it is a _private property that should not be accessed from outside.
Use new instead of Object.create. It's easier to remember if you are used to other OOP languages; and at the end new uses Object.create under the hood.
In other words, something like this:
var Person = function (name) {
this._name = name;
};
Person.prototype.sayHello = function () {
alert('My name is: ' + this._name);
};
var john = new Person('John');
john.sayHello();
EDIT
Some extra information:
Object.create vs new. Benchmark here. Although the question is for Node.js, I think the same behaviour is to be expected. (any correction is welcome)
Closures to emulate private properties: You can read about in this question.. The point that the private/closure properties do not belong to the object is a programming fact: they are accessible by the object methods but do not belong to the object. When using inheritance, that is a big mess. Besides, only methods that are declared in the constructor have access to the closure. Methods defined in the prototype do not.
Defining methods in the constructor or the prototype property: read this question, and take a look of this benchmark
EDIT 15/04/2016
The points I made here three years ago are still right from a performance point of view, but my opinion about what is the "recommended way" has changed a little in the meanwhile. Factory functions are in general a good option, which would be the OP's first approach. Just an example:
function Person(name) {
return {
sayHello: function () { alert('My name is: ' + name); }
};
}
and then just do:
var p = Person('John');
In this case you trade flexibility (no new coupling, ease of composition with other "mix-ins") and simplicity (no this mess, easy object instantiation) for some speed and memory. In general they are perfectly valid. If you have performance issues, and those are because of this way of creating objects, revert to another method. The Object.create approach is also good, falling somehow in the middle of new and factory functions (side note: the new class syntax is syntactic sugar for new+ prototype)
Summing up: my recommended way is starting from the simplest and easiest way of creating objects (factory functions) and then fall to other methods when you hit performance issues (which in most of cases is never).

There are many ways to create "Class" and "Object" in JS. I prefer this way:
var MyObject =
function(args) {
// Private
var help = "/php/index.php?method=getHelp";
var schedule = "/php/index.php?method=getSchedules";
var ajax = function(url, callback, type) {
//....
}
// Public
this.property = 0;
this.getInfo = function() {
// ...
}
// Constructor
function(data) {
this.property = data;
}(args);
};
var o = new MyObject();

Note: If you are more familiar with OOP syntax, you can also use class which is just syntactical sugar over existing prototype-based way.
Performance Comparison between 4 ways of creating object - with constructor (Chrome 61 - https://jsperf.com/create-object-ways)
Option A: Using return (Fastest 3x)
Option B: Using {key:value} (1.5x)
Option C: Using prototype (1x) <- Base
Option D: Using class (1.02x)
Option A seams to perform best. Note that some of the performance boost is because it avoids use of new or object.create. So just to have a fair trial, here is another test between method-only objects without constructor and properties.
Performance Comparison between 4 ways of creating methods-only object (Chrome 61 - https://jsperf.com/create-static-object-ways)
Option A: Using return (3.2x)
Option B: Using {key:value} (Fastest 3.3x)
Option C: Using prototype (1.8x)
Option D: Using class (1.9x)
Option B outperformed Option A a little. Also the bottleneck caused by object.create was more then new.
Best Practice
Option A (using return) is best performing in both the scenarios. This way can get little messy if you have many methods and properties.
I prefer to divide constructor & properties in separate object using Option A and methods in another object using Option B. This approach does need to send an extra instance reference in parameters but can be useful if you have multiple objects using same properties & constructor (Some OOP inheritance can also be achieved).
Example:
// Constructor & Properties Object (Using option A)
var UserData = function(request){
// Constructor
if ( request.name )
var name = request.name;
else
var name = 'Not Available';
if ( request.age )
var age = request.age;
else
var age = null;
// Return properties
return {
userName: name,
userAge: age
};
};
// Object methods (Using Option B)
var Adults = {
printName: function(instance){ // Read propery example
console.log( 'Mr. ' + instance.userName );
},
changeName: function(instance, newName){ // Write property example
instance.userName = newName;
},
foo: function(){
console.log( 'foo' );
}
};
// Object methods (Using Option B)
var Children = {
printName: function(instance){
console.log( 'Master ' + instance.userName );
},
bar: function(){
console.log( 'bar' );
}
}
// Initialize
var userData = UserData ( {name: 'Doe', age: 40} );
// Call methods
Adults.printName(userData); // Output 'Mr. Doe'
Children.printName(userData); // Output 'Master Doe'
Adults.foo(); // Output 'foo'
Children.bar(); // Output 'bar'
Adults.changeName(userData, 'John');
Adults.printName(userData); // Output 'Mr. John'

Related

JavaScript efficient solution for multi-inheritance

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

Inheritance with Object.create() method in javascript [duplicate]

Javascript 1.9.3 / ECMAScript 5 introduces Object.create, which Douglas Crockford amongst others has been advocating for a long time. How do I replace new in the code below with Object.create?
var UserA = function(nameParam) {
this.id = MY_GLOBAL.nextId();
this.name = nameParam;
}
UserA.prototype.sayHello = function() {
console.log('Hello '+ this.name);
}
var bob = new UserA('bob');
bob.sayHello();
(Assume MY_GLOBAL.nextId exists).
The best I can come up with is:
var userB = {
init: function(nameParam) {
this.id = MY_GLOBAL.nextId();
this.name = nameParam;
},
sayHello: function() {
console.log('Hello '+ this.name);
}
};
var bob = Object.create(userB);
bob.init('Bob');
bob.sayHello();
There doesn't seem to be any advantage, so I think I'm not getting it. I'm probably being too neo-classical. How should I use Object.create to create user 'bob'?
With only one level of inheritance, your example may not let you see the real benefits of Object.create.
This methods allows you to easily implement differential inheritance, where objects can directly inherit from other objects.
On your userB example, I don't think that your init method should be public or even exist, if you call again this method on an existing object instance, the id and name properties will change.
Object.create lets you initialize object properties using its second argument, e.g.:
var userB = {
sayHello: function() {
console.log('Hello '+ this.name);
}
};
var bob = Object.create(userB, {
'id' : {
value: MY_GLOBAL.nextId(),
enumerable:true // writable:false, configurable(deletable):false by default
},
'name': {
value: 'Bob',
enumerable: true
}
});
As you can see, the properties can be initialized on the second argument of Object.create, with an object literal using a syntax similar to the used by the Object.defineProperties and Object.defineProperty methods.
It lets you set the property attributes (enumerable, writable, or configurable), which can be really useful.
There is really no advantage in using Object.create(...) over new object.
Those advocating this method generally state rather ambiguous advantages: "scalability", or "more natural to JavaScript" etc.
However, I have yet to see a concrete example that shows that Object.create has any advantages over using new. On the contrary there are known problems with it. Sam Elsamman describes what happens when there are nested objects and Object.create(...) is used:
var Animal = {
traits: {},
}
var lion = Object.create(Animal);
lion.traits.legs = 4;
var bird = Object.create(Animal);
bird.traits.legs = 2;
alert(lion.traits.legs) // shows 2!!!
This occurs because Object.create(...) advocates a practice where data is used to create new objects; here the Animal datum becomes part of the prototype of lion and bird, and causes problems as it is shared. When using new the prototypal inheritance is explicit:
function Animal() {
this.traits = {};
}
function Lion() { }
Lion.prototype = new Animal();
function Bird() { }
Bird.prototype = new Animal();
var lion = new Lion();
lion.traits.legs = 4;
var bird = new Bird();
bird.traits.legs = 2;
alert(lion.traits.legs) // now shows 4
Regarding, the optional property attributes that are passed into Object.create(...), these can be added using Object.defineProperties(...).
Object.create is not yet standard on several browsers, for example IE8, Opera v11.5, Konq 4.3 do not have it. You can use Douglas Crockford's version of Object.create for those browsers but this doesn't include the second 'initialisation object' parameter used in CMS's answer.
For cross browser code one way to get object initialisation in the meantime is to customise Crockford's Object.create. Here is one method:-
Object.build = function(o) {
var initArgs = Array.prototype.slice.call(arguments,1)
function F() {
if((typeof o.init === 'function') && initArgs.length) {
o.init.apply(this,initArgs)
}
}
F.prototype = o
return new F()
}
This maintains Crockford prototypal inheritance, and also checks for any init method in the object, then runs it with your parameter(s), like say new man('John','Smith'). Your code then becomes:-
MY_GLOBAL = {i: 1, nextId: function(){return this.i++}} // For example
var userB = {
init: function(nameParam) {
this.id = MY_GLOBAL.nextId();
this.name = nameParam;
},
sayHello: function() {
console.log('Hello '+ this.name);
}
};
var bob = Object.build(userB, 'Bob'); // Different from your code
bob.sayHello();
So bob inherits the sayHello method and now has own properties id=1 and name='Bob'. These properties are both writable and enumerable of course. This is also a much simpler way to initialise than for ECMA Object.create especially if you aren't concerned about the writable, enumerable and configurable attributes.
For initialisation without an init method the following Crockford mod could be used:-
Object.gen = function(o) {
var makeArgs = arguments
function F() {
var prop, i=1, arg, val
for(prop in o) {
if(!o.hasOwnProperty(prop)) continue
val = o[prop]
arg = makeArgs[i++]
if(typeof arg === 'undefined') break
this[prop] = arg
}
}
F.prototype = o
return new F()
}
This fills the userB own properties, in the order they are defined, using the Object.gen parameters from left to right after the userB parameter. It uses the for(prop in o) loop so, by ECMA standards, the order of property enumeration cannot be guaranteed the same as the order of property definition. However, several code examples tested on (4) major browsers show they are the same, provided the hasOwnProperty filter is used, and sometimes even if not.
MY_GLOBAL = {i: 1, nextId: function(){return this.i++}}; // For example
var userB = {
name: null,
id: null,
sayHello: function() {
console.log('Hello '+ this.name);
}
}
var bob = Object.gen(userB, 'Bob', MY_GLOBAL.nextId());
Somewhat simpler I would say than Object.build since userB does not need an init method. Also userB is not specifically a constructor but looks like a normal singleton object. So with this method you can construct and initialise from normal plain objects.
TL;DR:
new Computer() will invoke the constructor function Computer(){} for one time, while Object.create(Computer.prototype) won't.
All the advantages are based on this point.
Sidenote about performance: Constructor invoking like new Computer() is heavily optimized by the engine, so it may be even faster than Object.create.
You could make the init method return this, and then chain the calls together, like this:
var userB = {
init: function(nameParam) {
this.id = MY_GLOBAL.nextId();
this.name = nameParam;
return this;
},
sayHello: function() {
console.log('Hello '+ this.name);
}
};
var bob = Object.create(userB).init('Bob');
Another possible usage of Object.create is to clone immutable objects in a cheap and effective way.
var anObj = {
a: "test",
b: "jest"
};
var bObj = Object.create(anObj);
bObj.b = "gone"; // replace an existing (by masking prototype)
bObj.c = "brand"; // add a new to demonstrate it is actually a new obj
// now bObj is {a: test, b: gone, c: brand}
Notes: The above snippet creates a clone of an source object (aka not a reference, as in cObj = aObj). It benefits over the copy-properties method (see 1), in that it does not copy object member properties. Rather it creates another -destination- object with it's prototype set on the source object. Moreover when properties are modified on the dest object, they are created "on the fly", masking the prototype's (src's) properties.This constitutes a fast an effective way of cloning immutable objects.
The caveat here is that this applies to source objects that should not be modified after creation (immutable). If the source object is modified after creation, all the clone's unmasked properties will be modified, too.
Fiddle here(http://jsfiddle.net/y5b5q/1/) (needs Object.create capable browser).
I think the main point in question - is to understand difference between new and Object.create approaches. Accordingly to this answer and to this video new keyword does next things:
Creates new object.
Links new object to constructor function (prototype).
Makes this variable point to the new object.
Executes constructor function using the new object and implicit perform return this;
Assigns constructor function name to new object's property constructor.
Object.create performs only 1st and 2nd steps!!!
In code example provided in question it isn't big deal, but in next example it is:
var onlineUsers = [];
function SiteMember(name) {
this.name = name;
onlineUsers.push(name);
}
SiteMember.prototype.getName = function() {
return this.name;
}
function Guest(name) {
SiteMember.call(this, name);
}
Guest.prototype = new SiteMember();
var g = new Guest('James');
console.log(onlineUsers);
As side effect result will be:
[ undefined, 'James' ]
because of Guest.prototype = new SiteMember();
But we don't need to execute parent constructor method, we need only make method getName to be available in Guest.
Hence we have to use Object.create.
If replace Guest.prototype = new SiteMember();
to Guest.prototype = Object.create(SiteMember.prototype); result be:
[ 'James' ]
Sometimes you cannot create an object with NEW but are still able to invoke the CREATE method.
For example: if you want to define a Custom Element it must derive from HTMLElement.
proto = new HTMLElement //fail :(
proto = Object.create( HTMLElement.prototype ) //OK :)
document.registerElement( "custom-element", { prototype: proto } )
The advantage is that Object.create is typically slower than new on most browsers
In this jsperf example, in a Chromium, browser new is 30 times as fast as Object.create(obj) although both are pretty fast. This is all pretty strange because new does more things (like invoking a constructor) where Object.create should be just creating a new Object with the passed in object as a prototype (secret link in Crockford-speak)
Perhaps the browsers have not caught up in making Object.create more efficient (perhaps they are basing it on new under the covers ... even in native code)
Summary:
Object.create() is a Javascript function which takes 2 arguments and returns a new object.
The first argument is an object which will be the prototype of the newly created object
The second argument is an object which will be the properties of the newly created object
Example:
const proto = {
talk : () => console.log('hi')
}
const props = {
age: {
writable: true,
configurable: true,
value: 26
}
}
let Person = Object.create(proto, props)
console.log(Person.age);
Person.talk();
Practical applications:
The main advantage of creating an object in this manner is that the prototype can be explicitly defined. When using an object literal, or the new keyword you have no control over this (however, you can overwrite them of course).
If we want to have a prototype The new keyword invokes a constructor function. With Object.create() there is no need for invoking or even declaring a constructor function.
It can Basically be a helpful tool when you want create objects in a very dynamic manner. We can make an object factory function which creates objects with different prototypes depending on the arguments received.
You have to make a custom Object.create() function. One that addresses Crockfords concerns and also calls your init function.
This will work:
var userBPrototype = {
init: function(nameParam) {
this.name = nameParam;
},
sayHello: function() {
console.log('Hello '+ this.name);
}
};
function UserB(name) {
function F() {};
F.prototype = userBPrototype;
var f = new F;
f.init(name);
return f;
}
var bob = UserB('bob');
bob.sayHello();
Here UserB is like Object.create, but adjusted for our needs.
If you want, you can also call:
var bob = new UserB('bob');
While Douglas Crockford used to be a zealous advocate of Object.create() and he is basically the reason why this construct actually is in javascript, he no longer has this opinion.
He stopped using Object.create, because he stopped using this keyword altogether as it causes too much trouble. For example, if you are not careful it can easily point to the global object, which can have really bad consequences. And he claims that without using this Object.create does not make sense anymore.
You can check this video from 2014 where he talks at Nordic.js:
https://www.youtube.com/watch?v=PSGEjv3Tqo0
new and Object.create serve different purposes. new is intended to create a new instance of an object type. Object.create is intended to simply create a new object and set its prototype. Why is this useful? To implement inheritance without accessing the __proto__ property. An object instance's prototype referred to as [[Prototype]] is an internal property of the virtual machine and is not intended to be directly accessed. The only reason it is actually possible to directly access [[Prototype]] as the __proto__ property is because it has always been a de-facto standard of every major virtual machine's implementation of ECMAScript, and at this point removing it would break a lot of existing code.
In response to the answer above by 7ochem, objects should absolutely never have their prototype set to the result of a new statement, not only because there's no point calling the same prototype constructor multiple times but also because two instances of the same class can end up with different behavior if one's prototype is modified after being created. Both examples are simply bad code as a result of misunderstanding and breaking the intended behavior of the prototype inheritance chain.
Instead of accessing __proto__, an instance's prototype should be written to when an it is created with Object.create or afterward with Object.setPrototypeOf, and read with Object.getPrototypeOf or Object.isPrototypeOf.
Also, as the Mozilla documentation of Object.setPrototypeOf points out, it is a bad idea to modify the prototype of an object after it is created for performance reasons, in addition to the fact that modifying an object's prototype after it is created can cause undefined behavior if a given piece of code that accesses it can be executed before OR after the prototype is modified, unless that code is very careful to check the current prototype or not access any property that differs between the two.
Given
const X = function (v) { this.v = v };
X.prototype.whatAmI = 'X';
X.prototype.getWhatIAm = () => this.whatAmI;
X.prototype.getV = () => this.v;
the following VM pseudo-code is equivalent to the statement const x0 = new X(1);:
const x0 = {};
x0.[[Prototype]] = X.prototype;
X.prototype.constructor.call(x0, 1);
Note although the constructor can return any value, the new statement always ignores its return value and returns a reference to the newly created object.
And the following pseudo-code is equivalent to the statement const x1 = Object.create(X.prototype);:
const x0 = {};
x0.[[Prototype]] = X.prototype;
As you can see, the only difference between the two is that Object.create does not execute the constructor, which can actually return any value but simply returns the new object reference this if not otherwise specified.
Now, if we wanted to create a subclass Y with the following definition:
const Y = function(u) { this.u = u; }
Y.prototype.whatAmI = 'Y';
Y.prototype.getU = () => this.u;
Then we can make it inherit from X like this by writing to __proto__:
Y.prototype.__proto__ = X.prototype;
While the same thing could be accomplished without ever writing to __proto__ with:
Y.prototype = Object.create(X.prototype);
Y.prototype.constructor = Y;
In the latter case, it is necessary to set the constructor property of the prototype so that the correct constructor is called by the new Y statement, otherwise new Y will call the function X. If the programmer does want new Y to call X, it would be more properly done in Y's constructor with X.call(this, u)
new Operator
This is used to create object from a constructor function
The new keywords also executes the constructor function
function Car() {
console.log(this) // this points to myCar
this.name = "Honda";
}
var myCar = new Car()
console.log(myCar) // Car {name: "Honda", constructor: Object}
console.log(myCar.name) // Honda
console.log(myCar instanceof Car) // true
console.log(myCar.constructor) // function Car() {}
console.log(myCar.constructor === Car) // true
console.log(typeof myCar) // object
Object.create
You can also use Object.create to create a new object
But, it does not execute the constructor function
Object.create is used to create an object from another object
const Car = {
name: "Honda"
}
var myCar = Object.create(Car)
console.log(myCar) // Object {}
console.log(myCar.name) // Honda
console.log(myCar instanceof Car) // ERROR
console.log(myCar.constructor) // Anonymous function object
console.log(myCar.constructor === Car) // false
console.log(typeof myCar) // object
I prefer a closure approach.
I still use new.
I don't use Object.create.
I don't use this.
I still use new as I like the declarative nature of it.
Consider this for simple inheritance.
window.Quad = (function() {
function Quad() {
const wheels = 4;
const drivingWheels = 2;
let motorSize = 0;
function setMotorSize(_) {
motorSize = _;
}
function getMotorSize() {
return motorSize;
}
function getWheelCount() {
return wheels;
}
function getDrivingWheelCount() {
return drivingWheels;
}
return Object.freeze({
getWheelCount,
getDrivingWheelCount,
getMotorSize,
setMotorSize
});
}
return Object.freeze(Quad);
})();
window.Car4wd = (function() {
function Car4wd() {
const quad = new Quad();
const spareWheels = 1;
const extraDrivingWheels = 2;
function getSpareWheelCount() {
return spareWheels;
}
function getDrivingWheelCount() {
return quad.getDrivingWheelCount() + extraDrivingWheels;
}
return Object.freeze(Object.assign({}, quad, {
getSpareWheelCount,
getDrivingWheelCount
}));
}
return Object.freeze(Car4wd);
})();
let myQuad = new Quad();
let myCar = new Car4wd();
console.log(myQuad.getWheelCount()); // 4
console.log(myQuad.getDrivingWheelCount()); // 2
console.log(myCar.getWheelCount()); // 4
console.log(myCar.getDrivingWheelCount()); // 4 - The overridden method is called
console.log(myCar.getSpareWheelCount()); // 1
Feedback encouraged.

JavaScript OOP classes and declarations

Im finding it really difficult to grasp OOP in javascript.
Normally I would expect to have to create a class, and then create objects from that class.
However, according to one tutorial the following makes an object.
var egg = {}
Have I not just made an object named egg without actually making a class.
If thats the case how would I make multiple objects from an object :S
Also according to a different tutorial an object is made like below, which is completely difference to what I was told above :S
var Block = function(){
}
Can anyone help me unravel my confusion :(
Both of the above examples are correct. to put it simply EVERYTHING in javascript is an object. classes do not exist but there are many ways to imitate them. my favorite method is as follows:
var myClass = function() { <----------------------------- class declaration
var prop1,
prop2, <------------------------------------ private properties
prop3;
var addMe = function( arg1, arg2 ) { <------------ private method
var result = arg1 + arg2;
return result;
}
var obj = { <------------------------------------- constructor method
Prop1: prop1,
Prop2: value2, <----------------------------- public properties
Prop3: value3,
Method: function() { <------------------------ public method
obj.prop3 = obj.prop1 + obj.prop2;
return obj.prop3;
}
}
obj.Prop4 = addme( prop1, prop2 ); <-------------- public property set
with the private method
return obj;
}
var myClassObj = new myClass;
myClassObj is now an object of myClass with four public properties
Prop1, Prop2, Prop3, Prop4 and one public method called Method
Javascript is a different language than those that you have learned so far. You can't expect things to work exactly as they do when you change languages.
A quick sneak peek: in javascript, you can assign a function to a variable. I bet on those other languages you have used, that was not possible:
var myCounter = 1;
var myFunction = function(x){ return x + 1; };
Going back to your question: In javascript there are no "real classes". There are just objects. I know this might sound confusing at first.
Javascript's object model is called "prototypal inheritance". It's different than "classical" (pun intended) inheritance. And it is also not very cleanly implemented.
Basically, you start with one reduced set of objects (Array, Function, Object, etc. are Objects, not classes) and then you use those objects to build others. The relationships between them can be "class-and-instance-like", but they don't have to. They can be other kinds of relationships, too.
Since there are no classes, you can't create them. But you can create a regular object, assign it to the variable Car, and just think "I'm going to use this object to create lots of other objects. And those other objects will have some attributes by default, like methods and stuff, so that they behave like cars". And the language allows you do do that. Car will behave like a class does in other languages, and the objects it produces will be "like instances of Car".
To javascript, though, they will look like objects with some relationships between them.
In a way, prototypal inheritance is a "superset" of classical inheritance. You can do classical inheritance, but also other things.
Have I not just made an object named egg without actually making a
class.
That's right. All you're doing there is instantiating the base Object object - you've not made anything that you can make instances of.
In JavaScript there is no formalised concept of classes - there is merely a simulation of them, achieved by instantiating rather than invoking functions.
function Animal() { this.animal = true; }
Animal.prototype.sayHi = function() { alert(this.name+' says hi!'); }
function Dog(name) { this.name = name; }
Dog.prototype = new Animal();
...
var fido = new Dog('Fido');
fido.sayHi(); //"Fido says hi!";
Note the 4th line is just one of several means of simulating inheritance.
So in JavaScript, classes and functions are both just functions. There is nothing inherent to prevent a function intended for instantiation from being called without the new operator, nor visa-versa.
In the former case, the common workaround is to check that the constructor is the 'class' (if invoked and not instantiated, the constructor will be Object) and re-route as necessary:
function Dog(name) {
//if we weren't instantiated, the constructor will be Object, not Dog
if(this.constructor != Dog) return new Dog(name);
this.name = name;
}
var fido = Dog(); //bad - invocation should be instantiation
Yes var egg = {} is an object, but its not an instance of an object.
In javascript, simply saying something in that way is basically js's idea of a singleton, meaning it is exactly what it equals.
//this is a js singleton, and all properties of this object are public.
var egg = {
name: 'humpty',
smush: function() { console.log('splat!'); },
weight: '4oz'
};
console.log(egg.weight); //4oz
whereas, the more traditional type of object would be making it a function that you can then instantiate:
var Egg = function( name, weight ) {
var name = name;
this.smush = function() { console.log('splat!'); }
this.weight = weight;
};
var e2 = new Egg('dumpty','6oz');
console.log(e2.name); //will not return name. (since i wrote var name and not this.name, its "private" and thus cannot be accessed.)
console.log(e2.weight); //4oz
You want to look at "Prototypal Inheritance" for JavaScript.
http://www.crockford.com/javascript/inheritance.html
Create an object oriented with jQuery. Make use of the constructor() method and access public and private methods from within the class scope.
/*
* myClass
*/
var myClass = function(options){
/*
* Variables accessible
* in the class
*/
var vars = {
myVar : ''
};
/*
* Can access this.method
* inside other methods using
* root.method()
*/
var root = this;
/*
* Constructor
*/
this.construct = function(options){
$.extend(vars , options);
};
/*
* Public method
* Can be called outside class
*/
this.myPublicMethod = function(){
console.log(vars.myVar);
myPrivateMethod();
};
/*
* Private method
* Can only be called inside class
*/
var myPrivateMethod = function() {
console.log('private method called');
};
/*
* Pass options when class instantiated
*/
this.construct(options);
};
/*
* USAGE
*/
/*
* Set variable myVar to new value
*/
var newMyClass = new myClass({ myVar : 'new Value' });
/*
* Call myMethod inside myClass
*/
newMyClass.myPublicMethod();

When to use the word "prototype" in adding new properties to an object in javascript?

I don't understand in JavaScript when to use the word "prototype" vs. using simple "dot" notation without the word "prototype". Can someone look at these code blocks and help me understand when you'd want to use one over the other?
with "prototype":
function employee(name,jobtitle)
{
this.name=name;
this.jobtitle=jobtitle;
}
var fred=new employee("Fred Flintstone","Caveman");
employee.prototype.salary=null;
fred.salary=20000;
console.log(fred.salary);
without "prototype":
function employee(name,jobtitle,salary)
{
this.name=name;
this.jobtitle=jobtitle;
this.salary=salary;
}
var fred=new employee("Fred Flintstone","Caveman", 20000);
console.log(fred.salary);
JavaScript objects have a property which is a pointer to another object. This pointer is the object's prototype. Object instances by default share the same prototype:
function Employee(name){
this.name = name;
}
Employee.prototype.company = "IBM";
Employee.prototype.who = function(){
console.log("My name is", this.name, "I work for", this.company);
}
var bob = new Employee('Bob');
var jim = new Employee('Jim');
// bob and jim are seperate objects, but each is linked to the same 'prototype' object.
jim.who(); // jim doesn't have a property called 'who', so it falls back to it's 'prototype', where who exists
// My name is Jim I work for IBM
bob.who();
// My name is Bob I work for IBM
// Bob leaves IBM for Microsoft
bob.company = "Microsoft"; // bob now has a property called 'company'. The value of which is 'Microsoft', which overrides bob's prototype property of the same name.
bob.who();
// My name is Bob I work for Microsoft
Employee.prototype.company = 'Facebook';
jim.who();
// My name is Jim I work for Facebook
bob.who(); // Bob is not affected by the change.
// My name is Bob I work for Microsoft
delete bob.company;
bob.who(); // bob no longer has it's own property 'company', so like jim, it drops down to the prototype object.
// My name is Bob I work for Facebook
The issues around JS and inheritance may be complex, but the answer to your question is relatively simple. Consider this code:
function Klass() { }
var obj1 = new Klass();
var obj2 = new Klass();
Now, if you add a property to obj1, that property exists only on obj1. Likewise obj2.
If you add a property to Klass, that property likewise exists only on Klass (the function object). It doesn't affect obj1 and obj2 at all.
But if you add a property to Klass.prototype, that property will then be present on both obj1 and obj2, as well as any future objects created via new Klass. If you then change the value of the property on the prototype, the changed value will be what you see on all those objects.
You could add code inside the body of the Klass function to add properties to this; that will then cause any future Klass objects to get those properties. But each object would have its own copy - which can add up, memory-wise, especially when the properties are methods -and those copies would not be affected by future changes to the body of Klass.
ES5's Object.create almost removes the need to hassle around with .prototype anymore.
So, to pick up #Gerry's example, you can go like
var Mammal = {
walk: function() {}
};
var Dog = Object.create(Mammal, {
bark: {
value: function() {}
}
}); // create a new object which [[prototype]] refers to Mammal
Dog.walk();
Dog.bark();
The prototype object is a little tricky to understand; however this article on OOP JavaScript can help shed some light.
In a nutshell, the prototype object provides a blueprint for a 'recipient' object - all you have to do is point the recipient's prototype property at your blueprint object. Note that you can have as many recipients of a prototype blueprint object as you like (so Car and Train can both point to a common Vehicle prototype object).
You are free to define both properties and functions in a prototype object which will any recipient objects will be able to use, eg:
var vehiclePrototype = {
// A property which will be supplied to the recipient
cost: 0,
// A method which will be supplied the recipient
move: function () {
// Your prototype can refer to 'this' still.
console.log("Moving " + this.name);
};
}
You can now create a Car which makes use of the vechiclePrototype:
// Factory method for creating new car instances.
function createCar(name) {
// Define the Car's constructor function
function Car(name) {
this.name = name;
}
// Point the car's prototype at the vechiclePrototype object
Car.prototype = vechiclePrototype;
// Return a new Car instance
return new Car(name);
}
// Create a car instance and make use of the Prototype's methods and properties
var mustang = createCar(mustang);
mustang.cost = 5000;
mustang.move();
A new Train object could be created in a similar fashion:
function createTrain(whilstleSound) {
// Define the Train's constructor function
function Train(name) {
this.whilstleSound = whilstleSound;
}
// Point the train's prototype at the vechiclePrototype object
Train.prototype = vechiclePrototype;
// Return a new Train instance
return new Train(name);
}
var ic125 = new Train("pooop pooop");
ic125.move();
One of the big advantages of using Prototypical inheritance all instances of both Car and Train share the exact same move function (instead of creating multiple instances of the same function) which results in a significant memory saving if there are many instances of these objects.
Ignore new, ignore .prototype they are just confusing notions. If you really want prototypical inheritance use Object.create but most of the time inheritance is completely overkill. (prototypical inheritance should only be used as an optimization technique).
When building classes just create objects and extend them.
var Walker = {
walk: function() {}
}
var Eater = {
eat: function () {}
}
var Dog = extend({}, Eater, Walker, {
bark: function () {},
sniffBehind: function () {}
})
function dog(dogName) {
return extend({}, Dog, {
name: dogName
})
}
var steveTheDog = dog("steve")
console.log(steveTheDog.name === "steve")
Use any arbitrary arity extend function you want, _.extend, jQuery.extend, pd.extend, etc.
pd implements extend as follows
function extend(target) {
[].slice.call(arguments, 1).forEach(function(source) {
Object.getOwnPropertyNames(source).forEach(function (name) {
target[name] = source[name]
})
})
return target
}
With prototype, you can extend in a 'cleaner' way, because you are separating the logic inside your constructor function from the properties and methods that define your object.
var Mammal = function() { ... };
Mammal.prototype = {
walk: function() { ... }
};
var Dog = function() { ... };
for (var prop in Mammal.prototype) {
Dog.prototype[prop] = Mammal.prototype[prop];
}
Dog.prototype.bark = function() { ... };
However, the above without prototype could look like this:
var Mammal = function() {
this.walk = function() { ... };
};
var Dog = function() {
Mammal.apply(this);
this.bark = function() { ... };
};
This way of extending Objects is however made irrelevant by modern JavaScript libraries like Underscore.js, or could be written much cleaner with the help of for example jQuery too.
You could use the word prototype to define some functionality across the application for particular type (Array, Function, Number of custom type)
For example you can extend all arrays with property sum:
const arrayPrototype = Array.prototype
Object.defineProperty(arrayPrototype, 'sum', {
get() { return this.reduce((a,b) => a + b, 0) }
})
When you've executed the chunk of code, all arrays have the property:
console.log([1,3,-1,10].sum) // prints 13

Choosing an OOP pattern in javascript

I've put these together with the help of others and several resources. I've made a fiddle of everything, and the stripped down code is posted below.
Basically I've learned how to use each of these patterns but I'm curious about the more fundamental differences between these approaches. Downstream code is practically identical with any of these patterns, but is there a reason why one should use one over another, beyond personal preference? Also though I've tried to gather up the most common patterns, please suggest your own if it's better.
Pattern 1 (Object Based):
var mouseDiff = {
"startPoint" : {"x" :0, "y" : 0},
"hypotenuse" : function(a,b) {
// do something
},
"init" : function(){
// do something
}
}
mouseDiff.init();
Pattern 2 (Most traditional as far as I know):
function MouseDiff() {
this.startPoint = {"x" :0, "y" : 0};
}
MouseDiff.prototype.hypotenuse = function(a,b) {
// do something
}
MouseDiff.prototype.init = function() {
// do something
}
var myMouse = new MouseDiff;
myMouse.init();
Pattern 3 (Making use of closure):
var MouseDiff2 = (function() {
var startPoint = {"x" :0, "y" : 0};
var hypotenuse = function(a,b) {
// do something
};
return {
hypotenuse: hypotenuse,
init : function(){
// do something
}
};
}());
MouseDiff2.init();
Pattern 1 is a singleton. If you only need one such object, it's just fine.
Pattern 2 builds new objects, and takes advantage of the prototype object so that when a new MouseDiff object is created, it will not create new copies of the functions (which are themselves data in JavaScript).
Pattern 3 requires more memory in comparison to a regular singleton but it offers static privacy.
I like the following pattern, as it covers various features, though it is really a combination of the constructor (pattern 2) and closure (pattern 3):
var MouseDiff = (function () {
var aStaticVariable = 'Woohoo!';
// And if you really need 100% truly private instance
// variables which are not methods and which can be
// shared between methods (and don't mind the rather
// big hassle they require), see
// http://brettz9.blogspot.com/search?q=relator
// (see also the new plans for a Map/WeakMap in ECMAScript)
function _APrivateStaticMethod () {
alert(aStaticVariable);
}
// An instance method meant to be called on the
// particular object as via ".call(this)" below
function _APrivateInstanceMethod () {
alert(this.startPoint.x);
}
// Begin Constructor
function MouseDiff() {
this.startPoint = {"x" :0, "y" : 0};
}
MouseDiff.prototype.hypotenuse = function(a,b) {
// do something
};
MouseDiff.prototype.init = function() {
// do something
_APrivateStaticMethod(); // alerts 'Woohoo!'
_APrivateInstanceMethod.call(this); // alerts 0 (but if not
// called with this, _APrivateInstanceMethod's internal
// "this" will refer (potentially dangerously) to the
// global object, as in the window in the browser unless
// this class was defined within 'strict' mode in which
// case "this" would be undefined)
};
return MouseDiff;
}());
var myMouse = new MouseDiff;
myMouse.init();
I do not know enough about JavaScript to tell you what if any performance differences exist between these approaches. Here are just two differences between these I noticed. I'm sure there are others.
Pattern 1 creates one object with those properties, including attached methods. Pattern 2 allows us to easily create many objects with the same methods attached, without rewriting them.
Pattern 3 is like a factory. Instead of relying on prototype to automatically attach these methods, the factory just creates them anew and returns the object. The usage of a closure allows us to hide the "member variables" of the object. There is no way to access startPoint or hypotenuse() except through the "public" interface returned.
Whenever I answer these types of theoretical JavaScript questions, I always fear there is some technical detail I am forgetting or overlooking. If so, let me know, and I will fix the answer.
Pattern two is my personally preference because it is the closest to traditional object oriented programming and allows for easy inheritance.
This post by John Resig (the guy behind JQuery) uses that method...
http://ejohn.org/blog/simple-javascript-inheritance/
[edit]
In fact, I don't think methods 1 or 3 have any benefits. 1 is, as someone else said, a singleton and does not allow multiple instances and 3... I don't know where to start with 3.
There is one more possible way to do this.
var MouseDiff = {};
(function(context) {
var privateVarialble = 0;
context.hypotenuse = function() {
//code here
};
context.int = function() {
//code here
}
})(MouseDiff);
Here we simply pass the namespace as an argument to a self-invoking function. The privateVarialble variable is private because it does not get assigned to the context.
We can even set the context to the global object (with a one word change!). Inside brackets (MouseDiff) make it (this). This is a big asset for library vendors – who can wrap their features in a self-invoking function and leave it to the user to decide whether they should be global or not.
http://www.jsoops.net/ is quite good for oop in Js. If provide private, protected, public variable and function, and also Inheritance feature. Example Code:
var ClassA = JsOops(function (pri, pro, pub)
{// pri = private, pro = protected, pub = public
pri.className = "I am A ";
this.init = function (var1)// constructor
{
pri.className += var1;
}
pub.getData = function ()
{
return "ClassA(Top=" + pro.getClassName() + ", This=" + pri.getClassName()
+ ", ID=" + pro.getClassId() + ")";
}
pri.getClassName = function () { return pri.className; }
pro.getClassName = function () { return pri.className; }
pro.getClassId = function () { return 1; }
});
var newA = new ClassA("Class");
//***Access public function
console.log(typeof (newA.getData));
// function
console.log(newA.getData());
// ClassA(Top=I am A Class, This=I am A Class, ID=1)
//***You can not access constructor, private and protected function
console.log(typeof (newA.init)); // undefined
console.log(typeof (newA.className)); // undefined
console.log(typeof (newA.pro)); // undefined
console.log(typeof (newA.getClassName)); // undefined
This has been answered elsewhere many times before but just to offer up some variety. ds.oop is a nice way to declare classes with constructors in javascript. It supports every possible type of inheritance (Including 1 type that even c# does not support) as well as Interfaces which is nice.
var Color = ds.make.class({
type: 'Color',
constructor: function (r,g,b) {
this.r = r; /* now r,g, and b are available to */
this.g = g; /* other methods in the Color class */
this.b = b;
}
});
var red = new Color(255,0,0); // using the new keyword to instantiate the class

Categories