Composition > Inheritance
Unless you’ve been coding under a rock, you know about the ES6/ES201* class syntax, which offers a constructor function and demands that you include super() if you wanna use this anywhere in your function. This is great syntactically if you’re used to classical OOP languages, but I think it’s masking the most powerful and flexible aspect of JS: prototypes and object concatenation. Besides, class/constructor/super are just playing a prototypical shell game under the hood.
There are several ways to use a functional approach to creating new objects and patterns, one of which is called the Factory Function, and I really like it. I like it so much in fact that I cooked up my own implementation and called it Unifactory. I named it that because it takes an arbitrary number of arguments, analyzes their type and returns them as properties of an object.
function Factory () {   const args = Array.from(arguments),      obj = {};     obj.__proto__ = defaultProps;     args.forEach(function(arg) {     if (typeof(arg) === 'function') {       obj[arg.name] = arg     } else if (typeof(arg) === 'object') {       for (let key in arg) {         obj[key] = arg[key]       }     } else {       obj[arg] = arg     }   });   return obj; } // Assign some default properties. ****/ const defaultProps = {   defaultPhrase: function (phrase) {     console.log(phrase);   } }; //*************************************/ // Create an observer pattern. ************/ const customEvent = Factory({   events: {},   add: function (event, callback) {     this.events[event] = callback;   },   dispatch: function (event, args) {     this.events[event](args);   } }); customEvent.add('walk', function (dest) {   console.log('I am walking to ' + dest); }); customEvent.dispatch('walk', 'the store.'); //*****************************************/ // Create some people with properties. ***************************/ let michael = Factory({name:'Michael'}, function speak (phrase) {   console.log('I am ' + michael.name + ' and ' + phrase); }); let zick = Factory({name:'Zick'}, function say (phrase, action) {   console.log('I am ' + zick.name + ', ' +         'and I '+ phrase + ' ' + action + '.'); }); zick = Object.assign(zick, {   retort: function (phrase) {     console.log(phrase);   } }); michael.speak('I\'m a developer.'); zick.say('might be', 'surfing'); zick.retort('I\'m probably enineering something now.'); michael.defaultPhrase('This is the default phrase.'); //****************************************************************/