Skip to content

Instantly share code, notes, and snippets.

@YozhEzhi
Created September 4, 2020 20:22
Show Gist options
  • Save YozhEzhi/fe587368283c79eabc6d4a98a79de9fd to your computer and use it in GitHub Desktop.
Save YozhEzhi/fe587368283c79eabc6d4a98a79de9fd to your computer and use it in GitHub Desktop.
/**
* Factory Functions.
*/
/*
* ES6 class vs Factory function:
* With class -- Be wary
*/
class Dog {
constructor() {
this.sound = 'woof';
}
talk() {
console.log(this.sound);
}
}
const sniffles = new Dog();
sniffles.talk(); // Outputs: 'woof'
/*
* Here's the issue.
* This will not work since - the `this` in talk() now refers to the DOM
* element selected by $(button) and not sniffles.
*/
$('button').click(sniffles.talk);
// Workaround -- explicit binding.
$('button').click(sniffles.talk.bind(sniffles));
/*
* Or in ES6 -- `this` inside an arrow function is always inherited
* from the enclosing scope.
*/
$('button').click(() => sniffles.talk());
// Factory function:
const dog = () => {
const sound = 'woof';
return {
// We are not using `this` at all.
talk: () => console.log(sound),
};
};
const sniffles = dog();
sniffles.talk(); // Outputs: 'woof'
$('button').click(sniffles.talk); // Works -- Outputs: 'woof'
/*
* Constructor function vs Factory function.
* The basic difference is that a constructor function is used with the `new` keyword:
*/
const objFromConstructor = new ConstructorFunction();
// A factory function is called like a "regular" function:
const objFromFactory = factoryFunction();
/*
* But for it to be considered a "factory" it would need to return a new instance
* of some object: you wouldn't call it a "factory" function if it just returned
* a boolean or something.
* This does not happen automatically like with new, but it does allow more
* flexibility for some cases. In a really simple example the functions
* referenced above might look something like this:
*/
function ConstructorFunction() {
this.someProp1 = '1';
this.someProp2 = '2';
}
ConstructorFunction.prototype.someMethod = function () {
/* whatever */
};
function factoryFunction() {
return {
someProp1: '1',
someProp2: '2',
someMethod() {
/* whatever */
},
/*
* someMethod() inside obj would lead to each object returned hold
* a different copy of someMethod which is something that we might not want.
* This is where using `new` and `prototype` inside the factory function would help.
*/
};
}
// Factory functions: Encapsulation using private properties.
function Car() {
// private variable
const location = 'Denver'; // PRIVATE
function year() {
// PRIVATE
self.year = new Date().getFullYear();
}
var self = {
make: 'Honda',
model: 'Accord',
color: '#cc0000',
paint(color) {
self.color = color;
},
};
if (!self.year) {
year();
}
return self;
}
const myCar = Car();
/*
* Factory functions: Dynamic objects.
* Since we can have public/private functions we can use if/else statements
* to easily manipulate our object structure.
* This gives ultimate flexibility to allow the root function ambiguity
* and allow parameters to determine what the object returned should be.
*/
function Address(param) {
let self = {};
if (param === 'dev') {
self = {
state: 'Colorado',
saveToLog() {
// write info to a log file
},
};
} else {
self = {
state: 'Colorado',
};
}
return self;
}
const devAddress = Address('dev');
const productionAddress = Address();
/**
* Getters and Setters.
*/
/*
* Using getters and setters -- Using Object.defineProperty
* When you define a property this way, you can do much more than just define a setter or getter. You may also pass following keys:
* configurable (false by default): if this is true, the property's configuration will be modifiable in future.
* enumerable (false by default): if true, the property will appear when looping over the object (for (var key in obj)).
*/
(function () {
const person = {
firstName: 'Jimmy',
lastName: 'Smith',
};
Object.defineProperty(person, 'fullName', {
get() {
return `${firstName} ${lastName}`;
},
set(name) {
const words = name.split(' ');
this.firstName = words[0] || '';
this.lastName = words[1] || '';
},
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment