Skip to content

Instantly share code, notes, and snippets.

@gregtatum
Created January 20, 2015 14:18
Show Gist options
  • Save gregtatum/d9436e31f977c462b6dd to your computer and use it in GitHub Desktop.
Save gregtatum/d9436e31f977c462b6dd to your computer and use it in GitHub Desktop.
Storing state in functions
/*
* Different ways to save state or configure a function
*
*/
//-------------------------------------------------
// Typical prototypical inheritance
var Talker = function( phrase ) {
this.phrase = phrase;
};
Talker.prototype = {
talk : function() {
console.log( this.phrase );
}
};
var sayThankYou = new Talker( "Why thank you so much." );
sayThankYou.talk();
// Mutation:
sayThankYou.phrase = "Gimme that!"; // easily mutable state
sayThankYou.talk();
//-------------------------------------------------
// Binding a function
var say = function() {
console.log(this.phrase);
};
var sayGoodbye = say.bind( {phrase: "That was fun, see you later!"} ); //
sayGoodbye();
// Mutation:
var spanish = {phrase: "Adios amigo."};
var sayAdios = sayGoodbyeSpanish = say.bind( spanish ); //
sayAdios();
spanish.phrase = "Hasta luego." // the bound state object is mutable
sayAdios();
//-------------------------------------------------
// Returning a function
var talk = function( phrase ) {
return function() {
// "phrase" is implicitely captured by this closure
// it maintains a persistent reference to the variable
console.log( phrase );
}
}
var sayHello = talk( "Why hello there" );
sayHello();
// sayHello is immutable in this case and cannot be reconfigured
// Any new configuration will have to create a new function
var sayHi = talk( "Hi!" );
sayHi();
// Caveat: objects are passed by reference and are still mutable.
// So you could pass in an object and modify it by reference.
@codelahoma
Copy link

With a proper deep cloning function, such as lodash's _.cloneDeep, you can create immutable private objects, too.

// Note: code requires lodash, and has not been tested

var talk = function( phraseObj ) {
  var obj = _.cloneDeep(phraseObj);
  return function() {
    console.log(obj.phrase);
  }
};

var english = {phrase: "Hello there!"};

var sayHello = talk(english);

sayHello();
// => Hello there!

english.phrase = "Goodbye now.";

sayHello();
// => Hello there!

@gregtatum
Copy link
Author

That's a good point. I tend to create a default configuration object and extend it. You could combine that with a deep clone (which I didn't below.)

// Note: code requires lodash, and has not been tested

var talk = function( phraseObj ) {

  var obj = _.extend({
    phrase: "Greetings my friend"
  }, phraseObj);

  return function() {
    console.log(obj.phrase);
  }
};

var sayGreeting = talk();
sayGreeting();
// => Greetings my friend

var english = {phrase: "Hello there!"};

var sayHello = talk(english);

sayHello();
// => Hello there!

english.phrase = "Goodbye now.";

sayHello();
// => Hello there!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment