Recently I watched a one of a talks by Douglas Crockford (his talks fascinate me, but always leave me confused). He gave an example of a constructor, but I don't quite understand how would I use it in practice:
function constructor(spec) {
var that = other_constructor(spec),
member,
method = function () {
//spec , member, method
};
that.method = method;
return that;
}
Maybe some one could give me a simple working example based on this pattern?
In classical object-oriented programming languages, a constructor is a special method used to initialize a newly created object once memory has been allocated for it. In JavaScript, as almost everything is an object, we're most often interested in object constructors.
A constructor is a special function that creates and initializes an object instance of a class. In JavaScript, a constructor gets called when an object is created using the new keyword. The purpose of a constructor is to create a new object and set values for any existing object properties.
This is Douglas Crockford original source as it appears in his slides:
function constructor(spec) {
let {member} = spec,
{other} = other_constructor(spec),
method = function () {
// member, other, method, spec
};
return Object.freeze({
method,
other
});
}
The following example is a more concrete version of Douglas Crockford's Object creation pattern 2014.
Douglas Crockford makes heavy use of ECMAScript 6 features like destructuring etc.!!
Start the code in node.js with following options (enable ES6):
node --harmony --harmony_destructuring demo.js
demo.js
// Douglas Crockford 2014 Object Creation
(function() {
'use strict';
function adress(spec) {
let {
street, city
} = spec,
logAdress = function() {
console.log('Adress:', street, city);
};
return Object.freeze({
logAdress
});
};
function person(spec) {
let {
preName,
name
} = spec, {
logAdress
} = adress(spec),
logPerson = function() {
// member, other, method, spec
console.log('Name: ', preName, name);
logAdress();
};
return Object.freeze({
logPerson,
logAdress
});
};
let myPerson = person({
preName: 'Mike',
name: 'Douglas',
street: 'Newstreet',
city: 'London'
});
myPerson.logPerson();
})();
According to Douglas Crockford’s talk, he avoids the use of:
Watch the original Crockford video: https://www.youtube.com/watch?v=PSGEjv3Tqo0
A good explanation for the Crockford Douglas Object Creation Pattern 2014 is this blog: https://weblogs.asp.net/bleroy/crockford%E2%80%99s-2014-object-creation-pattern
This is an example of using another constructor inside a factory function to return an object. In this case, other_constructor
is the constructor function, which is creating an object of the type other_constructor
(ideally in practice this would be capitalized). That object is stored in that
. In this factory function, method
is a defined function which is added to that
to extend the object's functionality in some way.
The difference between constructor and factory functions is that a factory function is just a normal function that returns an object, whereas a constructor function has this
pointing to the new object, and usually has to be called with the new
keyword preceding it.
A typical constructor function:
function Dog(breed, height, name){
this.breed = breed;
this.animalType = "dog";
this.height = height;
this.name = name;
// calling `return` isn't necessary here
}
And it's usage:
var lab = new Dog("labrador", 100, "Sugar"); // `new` is necessary (usually)
console.log(lab.animalType); // prints out "dog"
console.log(lab.height); // prints out 100
A typical factory function:
function createDog(breed, height, name){
var dog = {
breed: breed,
height: height,
animalType: "dog",
name: name
};
return dog;
// `return` is necessary here, because `this` refers to the
// outer scope `this`, not the new object
}
And its usage:
var lab = createDog("labrador", 100, "Sugar"); // notice no need for `new`
console.log(lab.animalType); // prints out "dog"
console.log(lab.height); // prints out 100
A good explanation of the difference between them and the different use cases of each is at Eric Elliot's blog
Vanilla JavaScript examples of Douglas Crockford's new constructor pattern with explanations:
console.clear();
var fauna = (function (){
privitizeNewVariables=function (specs) {
if (!specs.is_private) {
var members = Object.assign({}, specs);
members.is_private = true;
return members;
}
return specs;
},
newAnimal=function (specs) {
var members = privitizeNewVariables(specs);
members.inheritance_type_list = ['Animal'];
whenInDanger = function () {
try{
console.log('When in danger ', members.common_name);
members.movesBy();
}catch (e){
console.log('Error - whenInDanger() has no movesBy()');
}
};
var isA = function(object_type){
if (members.inheritance_type_list.indexOf(object_type)>-1) {
console.log(members.common_name, 'is a', object_type);
}else{
console.log(members.common_name, 'is not a', object_type);
}
}
return Object.freeze({
whenInDanger: whenInDanger,
isA: isA
});
},
newSnake=function (specs){
var members = privitizeNewVariables(specs);
members.movesBy = function () {
console.log('Moves By: slithering');
};
colorScheme = function () {
console.log('Color scheme :', members.color_scheme);
};
aPrivateFunction = function (){
console.log('I only exist inside a Snake object');
};
var an_animal = newAnimal(members);
members.inheritance_type_list.unshift('Snake');
return Object.freeze({
whenInDanger: an_animal.whenInDanger,
isA: an_animal.isA,
movesBy: members.movesBy,
colorScheme: colorScheme
});
};
return {
newAnimal:newAnimal,
newSnake: newSnake
}
})();
var animal_specs = {common_name: 'Alf the animal'};
var an_animal = fauna.newAnimal(animal_specs);
animal_specs.common_name = "does not change Alf's common_name";
an_animal.whenInDanger();
console.log(an_animal);
console.log('-');
var snake_specs = {common_name: 'Snorky the snake',
color_scheme:'yellow'};
var a_snake = fauna.newSnake(snake_specs);
a_snake.whenInDanger();
console.log('-');
a_snake.colorScheme();
a_snake.isA('Animal');
a_snake.isA('Snake');
a_snake.isA('Bear');
console.log('-');
console.log(fauna);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With