Reputation: 2790
I'm playing around with ES6 classes and my eventual goal is to understand the difference between classes vs constructor functions vs factory functions. My current understanding is that constructor functions and classes are basically using the same design pattern, classes just being the new syntax for the constructor functions. Based on this assumption, I'm trying to create some examples that display the contrast between class/constructor functions and factory functions.
With the examples below I aim to return new objects and some methods that are inherited.
My first example is rather straightforward with the class syntax.
Example #1: Classes
class Person {
constructor(name, age, location, occupation) {
this.name = name;
this.age = age;
this.location = location;
this.occupation = occupation;
}
printDescription() {
console.log(`My name is ${this.name} and I'm ${this.age} years old. I live in ${this.location} and I work as a ${this.occupation}.`);
}
}
const firstUser = new Person('Tom', 30, 'Sydney', 'Teacher');
firstUser.printDescription();
With the second example, I'm trying to replicate the first one with a different approach but I'm not sure if this is factory constructor or a factory function.
Example #2: ?
function PersonMaker (name, age, location, occupation) {
let person = {name, age, location, occupation};
person.printDetails = () => {
console.log(`My name is ${name} and I'm ${age} years old. I live in ${location} and I work as a ${occupation}.`);
};
return person;
}
const secondUser = PersonMaker('Johnny', 25, 'London', 'Driver');
secondUser.printDetails();
I need to clarify the pattern used in the second example and if it's not a factory function, how I could turn it into one?
Upvotes: 11
Views: 12261
Reputation: 541
To avoid passing many arguments, you can do it like this.
const PersonMaker = description => {
const {name, age, location, occupation} = description;
return {
printDetails: () => {
console.log(
`My name is ${name} and I'm ${age} years old. I live in ${location} and I work as a ${occupation}.`,
);
},
};
};
const secondUser = PersonMaker({
name: 'Johnny',
age: '25',
location: 'London',
occupation: 'Driver',
});
console.log(secondUser.printDetails());
Upvotes: 4
Reputation: 1437
Javascript takes its roots in Prototypal Inheritance:
// Prototype
var ProtoCtr = function ProtoCtr(name, age) {
this.name = name;
this.age = age;
};
ProtoCtr.prototype.printDetails = function printDetails() { console.log(`Hi, I'm ${this.name} and I'm ${this.age} years old`); };
var protoInstance = new ProtoCtr('John', 21);
protoInstance.printDetails();
In short:
Functions expose prototypes
Defines a this
context referring to the instance
Use the new
keyword to create an instance
Then, with ES6, the language offered the possibility to use the class
keyword (to please classical OO developers). It's a syntax which allow to group the declaration of your object in a block, avoiding to extend the prototype "manually". Under the hood, it does the exact same thing than the prototypal model, it's just an other way to write it.
// Class
class ClassCtr {
constructor(name, age) {
this.name = name;
this.age = age;
}
printDetails() {
console.log(`Hi, I'm ${this.name} and I'm ${this.age} years old`);
}
}
var classInstance = new ClassCtr('John', 21);
classInstance.printDetails();
Key concepts are about the same, but you don't use prototype to expose methods to your instance but declare it directly inside the class
block.
Then, there is the factory pattern, which is not a language specs but a pattern, a way to do things. It's my personal favorite. The factory function builds and return the instance. With this method, you get rid of the new
keyword and don't need the this
anymore to refer to you instance:
// Factory
var factoryCtr = function factoryCtr(name, age) {
var instance = {
name: name,
age: age,
printDetails: function printDetails() { console.log(`Hi, I'm ${instance.name} and I'm ${instance.age} years old`); }
};
return instance;
}
var factoryInstance = factoryCtr('John', 21);
factoryInstance.printDetails();
Even if Class is not covered by this talk, I recommand you to watch this video: https://www.youtube.com/watch?v=ya4UHuXNygM
I hope this helped :)
Upvotes: 4
Reputation: 1037
Since it returns an object its a factory function - it's already explained there.
Constuctor functions behaviour different from this, it doesn't return value:
function Person(name, age, location, occupation){
this.name = name
this.age = age
this.location = location
this.occupation = occupation
}
Person.prototype.printDetails = function(){
console.log(`My name is ${this.name} and I'm ${this.age} years old. I live in ${this.location} and I work as a ${this.occupation}.`);
};
const secondUser = new Person('Johnny', 25, 'London', 'Driver');
secondUser.printDetails();
I used definition of methods by extending prototype just to separate constructor function, and you can still define a methods inside constructor function as well:
function Person(name, age, location, occupation){
this.name = name
this.age = age
this.location = location
this.occupation = occupation
this.printDetails = function(){
console.log(`My name is ${this.name} and I'm ${this.age} years old. I live in ${this.location} and I work as a ${this.occupation}.`);
};
}
const secondUser = new Person('Johnny', 25, 'London', 'Driver');
secondUser.printDetails();
Upvotes: 7