Last active
September 9, 2017 18:55
-
-
Save jdoleary/82ee467c518b76c6b5cd57a57dfa8ec8 to your computer and use it in GitHub Desktop.
Flexible Object Composition with "Constructor"
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
How to compose object AND change things inside the factories used to compose | |
while maintaining an exact reference to the original object and being able to | |
access variables from any factory. | |
*/ | |
var a = {a:1}; | |
function factory(state){ | |
// State is still the original object: | |
console.log(state===a); // true | |
var changed = Object.assign({newInFact:3},state); | |
// Both factories have access to the variables from each other: | |
return Object.assign(changed,{log:()=>console.log(state.a,state.aa,state.newInFact,state.newIn2)}); | |
} | |
function factory2(state){ | |
// State is still the original object: | |
console.log(state===a); // true | |
var changed = Object.assign({newIn2:4},state); | |
// Both factories have access to the variables from each other: | |
return Object.assign(changed,{log2:()=>console.log(state.a,state.aa,state.newInFact,state.newIn2)}); | |
} | |
// This is the most important line as it reassigns the context of state in all the factories to be the same as `a`, see Part 2 | |
var composedObject = Object.assign(a,{aa:2},factory(a),factory2(a)); | |
composedObject.log(); // 1 2 3 4 | |
composedObject.log2(); // 1 2 3 4 | |
console.log(composedObject===a) // true | |
/*Part 2*/ | |
var b = {a:1}; | |
function factory(state){ | |
// State is still the original object: | |
console.log(state===b); // true | |
var changed = Object.assign({newInFact:3},state); | |
// Both factories have access to the variables from each other: | |
return Object.assign(changed,{log:()=>console.log(state.a,state.newInFact)}); | |
} | |
var c = factory(b) | |
c.log(); //1 undefined | |
console.log(c);//{newInFact: 3, a: 1, log: ƒ} | |
// As you can see, even tho c has `newInFact` it comes out as `undefined` when logged in the function because `state` is only {a:1} | |
// That is why you need `var c = Object.assign(b,factory(b));` to give `b` the factories properties as the factory still holds a reference to b | |
// This can also be accomplished inside the factory like so: | |
var bb = {a:1,defaultParam:2}; | |
function factory(state){ | |
// State is still the original object: | |
console.log(state===bb); // true | |
// State is the last argument here in order to override the defaultParams | |
var changed = Object.assign({defaultParam:9,newInFact:8},state); | |
changed.newInFact = changed.defaultParam+1; | |
// Both factories have access to the variables from each other: | |
return Object.assign(state, changed,{log:()=>console.log(state.a,state.defaultParam,state.newInFact)}); | |
} | |
var c = factory(bb) | |
c.log(); //1 2 3 | |
// This grants the advantage of having default parameters in the factory that are overriden by the state that passed in. | |
// Then the data can be manipulated and as long as it ends in `return Object.assign(state, ...);` then `state` within all of | |
// the factory's functions will still reference the original object. | |
console.log(c);//{newInFact: 3, a: 1, log: ƒ} |
It's important to understand that Object.assign() assigns the properties of the latter objects to that of the objected passed in as the first parameter. It mutates the first parameter.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The only place
state
should be used inside a factory is in Object.assign() and inside of functions that are in Object.assign(). Anything outside of that should usechanged
.