Skip to content

Instantly share code, notes, and snippets.

@raineorshine
Created March 26, 2014 14:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save raineorshine/9784271 to your computer and use it in GitHub Desktop.
Save raineorshine/9784271 to your computer and use it in GitHub Desktop.
Simulating private instance methods.
// This is probably the cleanest approach, but forces you to use
// privateMethod.call(this) syntax.
// MyClass module
(typeof module !== 'undefined' ? module.exports : window).MyClass = (function() {
// private
var sayHi = function() {
return 'Hi ' + this.name;
};
// define constructor
var MyClass = function() {
this.name = 'Alexa';
};
// public prototype
MyClass.prototype.happyHi = function() {
return sayHi.call(this) + '!!!';
};
// return constructor
return MyClass;
})();
// TESTS
var a = new MyClass('Alexa');
console.log(a.name, 'Alexa');
console.log(a.sayHi, undefined, 'Private methods are undefined');
console.log(a.happyHi(), 'Hi Alexa!!!', 'Public methods can access private methods with the correct context');
a.name = 'Bob';
console.log(a.happyHi(), 'Hi Bob!!!', 'Methods reference the actual instance variables, not copies.');
var b = new MyClass('Anna');
b.name = 'Satya';
console.log(a.happyHi(), 'Hi Bob!!!', 'Instances have their own instance variables as you\'d expect.');
// This is trick to enable normal this.privateMethod syntax by creating a
// hidden context object that hosts all the public and private methods and sets
// its prototype to the actual instance. This will break in some circumstances
// where methods expect to interact witht the actual host object instead of
// a fake prototype.
// MyClass module
(typeof module !== 'undefined' ? module.exports : window).MyClass = (function() {
var extend = function() {
var host = arguments[0] || {};
for(var i=1; i<arguments.length; i++) {
for(var key in arguments[i]) {
host[key] = arguments[i][key];
}
}
return host;
};
// private methods
var priv = {
// private function accessing instance variable
sayHi: function() {
return 'Hi ' + this.name;
}
};
// public methods
var pub = {
happyHi: function() {
return this.sayHi() + '!!!';
}
};
// define constructor
var MyClass = function(name) {
this.name = name;
// create a hidden context with the new instance as its prototype object
var hiddenContext = Object.create(this);
extend(hiddenContext, priv, pub);
// this could be done with _.bindAll
for(var methodName in pub) {
this[methodName] = pub[methodName].bind(hiddenContext);
}
};
// return constructor
return MyClass;
})();
// TESTS
var a = new MyClass('Alexa');
console.log(a.name, 'Alexa');
console.log(a.sayHi, undefined, 'Private methods are undefined');
console.log(a.happyHi(), 'Hi Alexa!!!', 'Public methods can access private methods with the correct context');
a.name = 'Bob';
console.log(a.happyHi(), 'Hi Bob!!!', 'Methods reference the actual instance variables, not copies.');
var b = new MyClass('Anna');
b.name = 'Satya';
console.log(a.happyHi(), 'Hi Bob!!!', 'Instances have their own instance variables as you\'d expect.');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment