Skip to content

Instantly share code, notes, and snippets.

@jdoleary
Last active September 9, 2017 18:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jdoleary/82ee467c518b76c6b5cd57a57dfa8ec8 to your computer and use it in GitHub Desktop.
Save jdoleary/82ee467c518b76c6b5cd57a57dfa8ec8 to your computer and use it in GitHub Desktop.
Flexible Object Composition with "Constructor"
/*
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: ƒ}
@jdoleary
Copy link
Author

jdoleary commented Sep 9, 2017

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 use changed.

@jdoleary
Copy link
Author

jdoleary commented Sep 9, 2017

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