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 co
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:
Object
constructorGetSpeed
getter)The simplest pattern is:
function RabbitFactory() {
return {
speed: 3,
getSpeed() { return this.speed; }
};
}
var rabbit = RabbitFactory();
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
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.
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();
Basically I would distinguish 3 approaches to create an object in JS:
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.