Created
March 26, 2014 14:16
-
-
Save raineorshine/9784271 to your computer and use it in GitHub Desktop.
Simulating private instance methods.
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
// 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 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
// 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