JavaScript Prototype and Encapsulation - javascript

Sorry I'm probably being a realy noob here...but:
I have the following javascript object:
jeeni.TextField = (function(){
var tagId;
privateMethod = function(){
console.log("IN: privateMethod");
}
publicMethod = function(){
console.log("IN: publicMethod: " + this.tagId);
}
jeeni.TextField = function(id){
console.log("Constructor");
this.tagId = id;
}
jeeni.TextField.prototype = {
constructor: jeeni.TextField,
foo: publicMethod
};
return jeeni.TextField;
}());
Now when I run the following code I get the corresponding result:
var textField1 = new jeeni.TextField(21); // Outputs: Constructor
textField1.foo(); // Outputs: IN: publicMethod: 21
console.log(textField1.tagId); // Outputs: 21
console.log(textField1.privateMethod); // Outputs: undefined
So my question is why is privateMethod hidden and tagId is not. I want them both to be private scope.
Please help a noob.
Thanks

You mixed up two ways of creating modules. The problem is that the private var tagId is not the same thing as this.tagId
Let me start with a version that works and is similiar to what I normally do with AMD modules:
jeeni.TextField = (function(){
//here you can put a variable common to all instances
return {
init:function(id){
var tagId = id;
console.log("Constructor");
function privateMethod(){
console.log("IN: privateMethod");
}
function publicMethod(){
console.log("IN: publicMethod: " + tagId);
}
return {
foo:publicMethod
};
}
})();
var textField1 = jeeni.TextField.init(21); //creates instance
textField1.foo(); // Outputs: IN: publicMethod: 21
console.log(textField1.tagId); // Outputs: undefined
console.log(textField1.privateMethod); // Outputs: undefined
This has one disadvantage: for every object instance the functions are copied in the memory. That's the only reason to use prototypes. But if you want private variables, you'll probably waste some RAM anyway.
In your code, if you replace this.tagId with just tagId you'll be using the private variable, but it will be just one, common for all instances.
I will think about making your code work and edit if I find a way to do that.
[edit]
What Stephen did is close to what you expected your code to do. I wouldn't want to exlain how it works and why to a co-worker though.
[edit]
BTW. Take a look at require.js and AMD (module definition)

Your code is almost right. Just lose this when accessing tagId. this.tagId is setting a property on that particular TextField, not the var tagId you declared up top.
If you set a variable x without using var, as in x = 2, it finds the nearest x going up the scope chain; if none is found it ends up being a property of the global object (window). In your case you can modify tagId from any of those functions since they can reach it one level up. That's why it's used as a "private" variable, the same way privateMethod can be reached.
And since jeeni.TextField is being set to the return value from the whole function, you don't to reference jeeni on the inside.
jeeni.TextField = (function(){
var tagId;
var privateMethod = function(){
console.log("IN: privateMethod");
}
var publicMethod = function(){
console.log("IN: publicMethod: " + tagId);
}
function TextField(id){
// this === the new instance of TextField
console.log("Constructor", this);
// set the tagId variable which is in scope here
tagId = id;
}
TextField.prototype.foo = publicMethod
return TextField
}());
Note that I also added var before the public/private methods, otherwise you are leaking them to the global scope. You could just as well use function publicMethod(){ ... }, which is usually better for debugging.
In case you're confused, x = function(){}... is not the same as function x(){}. See chapter 2 of "Named function expressions demystified".
With that cleared up, this is still probably not what you want, since with this code tagId will be shared between all instances of TextField. The usual method of having one tagId per instance would be making it a "public" property, which is exactly what you had done (I don't see any problem with this, since id itself comes from the outside):
...
// var tagId -> drop this
publicMethod = function(){
console.log("IN: publicMethod: " + this.tagId);
}
function TextField(id){
console.log("Constructor");
this.tagId = id;
}
Now let's make tagId private and specific for each instance. The simplest way to do it, without creating new functions every time, is to create a private object (let's call it tags) that holds all the data, and give each instance it's own ID (tf_id). The ID is visible, but since the tags object is private you can only access the data by using one of the public methods:
jeeni.TextField = (function(){
var tags = {}
, uid = 0;
privateMethod = function(){
console.log("IN: privateMethod");
}
publicMethod = function(){
console.log("IN: publicMethod: " + tags[this.tf_id].tagId);
}
function TextField(id){
this.tf_id = uid++
tags[this.tf_id] = id
}
TextField.prototype.foo = publicMethod
return TextField
}());

Apparently I read the question incorrectly.
If you set a property of something (i.e. this.tagId) it immediately becomes accessible to the world. You've wrapped your constructor in the wrong spot - change it to something like this instead:
jeeni.TextField = (function(){
var TextField = function(id){
console.log("Constructor");
var tagId = id;
privateMethod = function(){
console.log("IN: privateMethod");
}
this.publicMethod = function(){
console.log("IN: publicMethod: " + tagId);
}
}
TextField.prototype = {
constructor: TextField
};
return TextField;
}());
Basically, you won't be able to put anything on the prototype that requires access to those protected variables.

There are a few problems here. The first is that you are messing about with global variables in a not-normal way. Effectively you have this:
var globalVar;
globalVar = function() {
globalVar = function() {
//... stuff
}
return globalVar;
}
What are you hoping that will do? The normal way to write this is:
function myObj(id) {
// in javascript the function *is* the constructor
tagId = id;
function someMethod() {
//...
}
}
var globalVar = new myObj(someId);
Although it's better to avoid globals.
In the example you give, this is the actual object you're returning:
function(id){
console.log("Constructor");
this.tagId = id;
}
So no, it doesn't have a privateMethod or publicMethod for that matter. Since this function object is constructed in the scope of the enclosing function, the constructor could access privateMethod, which is where the privacy of it comes from.
To see how to do private variables and methods in javascript, go to the wizard himself:
http://javascript.crockford.com/private.html

Related

Javascript most simple use of prototype with `self = this` and callback

I have read a few questions like this about it, but I still can't make it work:
Here is my simplified test:
var person = function(name, job)
{
var self = this;
self.name = null;
self.callMe = function()
{
alert(self.name + ' please!');
};
self.init = function()
{
self.name = name;
setTimeout(function(){self.callMe()}, 1000);
}();
}
...
person.prototype.callMe = function()
{
alert('Mister ' + this.name + ' please!');
};
var jonh = new person('john');
var joe = new person('joe');
can test it here: http://codepen.io/anon/pen/bqxmPa?editors=0010
1. Why is the callMe() function in use the original one?
I have read that I must use this to be able to use prototype, which makes sens: since I call a function stored in var self from self.init() the function stored in that var will not be modified by my later prototype... But then how do I do the callback if I don't store the this in self?
2. If I override callMe like person.callMe = function(){}; it will do the same, then why should I use prototype?
I also understand that placing a method in a prototype is good for performance as it is not duplicated in each instance but still shared among them.
Thanks for your teaching!
1.) This is how prototypical inheritence works. When the callback for callMe returns, the code tries to resolve the variable self inside the callback's execution context. Since it is not defined there, it goes up the prototype chain and finds it defined in the execution context on the same level where the callMe and init functions are defined. As callMe is defined on this level, it will simply execute it. If it was not defined on this level, it would execute the function defined on the prototype.
2) If you want to subscribe to OO JS, putting the functions on the prototype will make it clear that they are uhh 'interface methods'. What you are doing here is effectively defining instance methods everytime you 'new' up a class.
Here's how I would implement the Person class as OO
var Person = function(name, job){
this.name = name;
this.init();
};
Person.prototype.init = function(){
setTimeout((function() {
this.callMe();
}).apply(this), 1000);
};
Person.prototype.callMe = function(){
alert('Mister ' + this.name + ' please!');
};
var jonh = new Person('john');
var joe = new Person('joe');

How to call private & public functions inside namespace [duplicate]

How do I call a public function from within a private function in the JavaScript Module Pattern?
For example, in the following code,
var myModule = (function() {
var private1 = function(){
// How to call public1() here?
// this.public1() won't work
}
return {
public1: function(){ /* do something */}
}
})();
This question has been asked twice before, with a different accepted answer for each.
Save a reference to the return object before returning it, and then use that reference to access the public method. See answer.
Save a reference to the public method in the closure, and use that to access the public method. See answer.
While these solutions work, they are unsatisfactory from an OOP point of view. To illustrate what I mean, let's take a concrete implementation of a snowman with each of these solutions and compare them with a simple object literal.
Snowman 1: Save reference to return object
var snowman1 = (function(){
var _sayHello = function(){
console.log("Hello, my name is " + public.name());
};
var public = {
name: function(){ return "Olaf"},
greet: function(){
_sayHello();
}
};
return public;
})()
Snowman 2: Save reference to public function
var snowman2 = (function(){
var _sayHello = function(){
console.log("Hello, my name is " + name());
};
var name = function(){ return "Olaf"};
var public = {
name: name,
greet: function(){
_sayHello();
}
};
return public;
})()
Snowman 3: object literal
var snowman3 = {
name: function(){ return "Olaf"},
greet: function(){
console.log("Hello, my name is " + this.name());
}
}
We can see that the three are identical in functionality and have the exact same public methods.
If we run a test of simple overriding, however
var snowman = // snowman1, snowman2, or snowman3
snowman.name = function(){ return "Frosty";}
snowman.greet(); // Expecting "Hello, my name is Frosty"
// but snowman2 says "Hello, my name is Olaf"
we see that #2 fails.
If we run a test of prototype overriding,
var snowman = {};
snowman.__proto__ = // snowman1, snowman2, or snowman3
snowman.name = function(){ return "Frosty";}
snowman.greet(); // Expecting "Hello, my name is Frosty"
// but #1 and #2 both reply "Hello, my name is Olaf"
we see that both #1 and #2 fail.
This is a really ugly situation. Just because I've chosen to refactor my code in one way or another, the user of the returned object has to look carefully at how I've implemented everything to figure out if he/she can override my object's methods and expect it to work! While opinions differ here, my own opinion is that the correct override behavior is that of the simple object literal.
So, this is the real question:
Is there a way to call a public method from a private one so that the resulting object acts like an object literal with respect to override behavior?
You can use this to get the object your privileged method greet was called on.
Then, you can pass that value to your private method _sayHello, e.g. using call, apply, or as an argument:
var snowman4 = (function() {
var _sayHello = function() {
console.log("Hello, my name is " + this.name);
};
return {
name: "Olaf",
greet: function() {
_sayHello.call(this);
}
};
})();
Now you can do
var snowman = Object.create(snowman4);
snowman.greet(); // "Hello, my name is Olaf"
snowman.name = "Frosty";
snowman.greet(); // "Hello, my name is Frosty"
And also
snowman4.greet(); // "Hello, my name is Olaf"
snowman4.name = "Frosty";
snowman4.greet(); // "Hello, my name is Frosty"
With module pattern, you hide all the innates of an object in local variables/functions, and usually employ those in your public functions. Each time a new object is created with a module pattern, a new set of exposed functions - with their own scoped state - is created as well.
With prototype pattern, you have the same set of methods available for all objects of some type. What changes for these methods is this object - in other words, that's their state. But this is never hidden.
Needless to say, it's tough to mix those. One possible way is extracting the methods used by privates into a prototype of the module's resulting object with Object.create. For example:
var guardian = function() {
var proto = {
greet: function () {
console.log('I am ' + this.name());
},
name: function() {
return 'Groot';
}
};
var public = Object.create(proto);
public.argue = function() {
privateGreeting();
};
var privateGreeting = public.greet.bind(public);
return public;
};
var guardian1 = guardian();
guardian1.argue(); // I am Groot
var guardian2 = guardian();
guardian2.name = function() {
return 'Rocket';
};
guardian2.argue(); // I am Rocket
var guardian3 = guardian();
guardian3.__proto__.name = function() {
return 'Star-Lord';
};
guardian3.argue(); // I am Star-Lord

JavaScript Module Pattern - Private variables vs. Static variables

So this is an example of the famous JavaScript Module Pattern:
var Person = (function() {
var _name; // so called 'private variable'
function Person(name) {
_name = name;
}
Person.prototype.kill = function() {
console.log(_name + ' has been shot');
};
return Person;
})();
var paul = new Person('Paul');
paul.kill();
So far so good right? This logs 'Paul has been shot' to the console, which is what we want.
But.
Is _name really a private variable? I would define a private variable as a variable that belongs to an instance of an object, which is not accessible for the outside world. The last part works, I can not access _name from outside the closure.
But if I do this:
var paul = new Person('Paul');
var bran = new Person('Bran');
paul.kill();
bran.kill();
This will then log 'Bran has been shot', twice. No Paul there. So _name is actually shared with all instances of my Person object. That's what I would define as a 'static variable', although it's also not accessible from outside.
So is there any way to create a real private member variable with the module pattern? One that is not static.
Something that also happens a lot is defining this._name inside the constructor function, but that kills the private part, it's now accessible from outside:
function Person(name) {
this._name = name;
}
var bran = new Person();
console.log(bran._name); // yep, accessible
Question:
So. Private is not really private, just static. How do we create a real private member variable with the module pattern? A variable which belongs to an instance, which is not static, and a variable which is not accessible from the outside.
You're right; _name is more of a static variable. It is kept in the closure that contains the constructor, so every use of the constructor will use that same variable. And remember, this has nothing to do with classes, and everything to do with closures and functions. It can be pretty handy, but it isn't how you do private members.
Unsurprisingly, Douglas Crockford has a page devoted to private members in Javascript.
In order to make private members, you have to go 'one level deeper'. Don't use a closure outside of the constructor; use the constructor as the closure. Any variables or methods defined inside the constructor are obviously not usable by the outside world. In fact, they aren't accessible by the object, either, so they are rather extremely 'private'.
We want to use our private members though. :) So what to do?
Well, in the constructor, do this:
var Klass = function () {
var private = 3;
this.privileged = function () { return private; };
};
and then:
var k = Klass();
console.log(k.privileged()); // 3
See how that's using the constructor as a closure? this.privileged lives on, attached to the object, and thus private lives on, inside this.privileged's closure.
Unfortunately, there's one problem with private and privileged methods in Javascript. They must be instantiated from scratch each time. There is no code sharing. That's obviously what we want with private members, but it isn't ideal for methods. Using them slows down object instantiation and uses more memory. It's something to keep in mind when/if you run into efficiency problems.
"Real private member variables" and prototype based methods do not play nice together. The only way achieve what you want is to create all methods in the constructor.
var Person = (function() {
function Person(name) {
this.kill = function() {
console.log(name + ' has been shot');
};
}
return Person;
})();
var paul = new Person('Paul');
var bran = new Person('Bran');
paul.kill(); // Paul has been shot
bran.kill(); // Bran has been shot
But this will use more memory and be slower since each instance has a unique version of the kill function.
Conventionally, the underscore prefix is used for semi-private instance properties, as long as the data exposed is not a security risk. Most consumers of your javascript code know not to mess with underscore prefixed properties.
Some more reading you may find useful is here.
The problem is that your _name variable is outside the Person scope and shared between all Person instances. Do something like the following instead :
(function() {
var Person = function(name) {
var _name = name; // so called 'private variable'
this.getName = function()
{
return _name;
}
this.kill = function()
{
console.log(this.getName() + ' has been shot');
}
}
/*Alternative
Person.prototype.kill = function() {
console.log(this.getName() + ' has been shot');
};*/
window.Person = Person;
})();
var paul = new Person('Paul');
var bran = new Person('Bran');
paul.kill();
bran.kill();
A variable that needs to be private in instance scope has to be in such scope, for example:
function Person(name) {
var _name = name;
this.kill = function() {
console.log( _name + ' has been shot' );
}
}
A drawback of this is that kill has to be defined in a scope that also has access to the private variable.
In order to create a private var, you should put it inside the constructor, so your code would be like this:
var Person = (function() {
function Person(name) {
// since name is a param, you don't even have to create a _name var
// and assign name to it
this.getName = function () {
return name;
};
}
Person.prototype.kill = function() {
console.log(this.getName() + ' has been shot');
};
return Person;
})();
var paul = new Person('Paul');
paul.kill();
You can also declare .kill inside the constructor:
var Person = (function() {
function Person(name) {
this.kill = function() {
console.log(name + ' has been shot');
};
}
return Person;
})();
var paul = new Person('Paul');
paul.kill();

How can i call a public method from within a private one when using the javascript Module Pattern?

I would like to call a public method from a private one but the property "this" refers to the window object.
Please note i am trying to apply the module pattern. You can find a working code example at jsfiddle.net
// how can i access a public method from a private one?
// (in this example publicAlert from privateMethod)
// this refers to the window object.
$(function() {
var modulePattern = (function($)
{
var privateMethod = function()
{
appendText("called privateMethod()");
this.publicAlert();
};
var appendText = function(texToAppend)
{
var text = $('#output').text() + " | " + texToAppend;
$('#output').text(text);
};
return {
publicMethod : function()
{
appendText("called publicMethod()");
privateMethod();
},
publicAlert : function()
{
alert("publicAlert");
}
};
});
mp = new modulePattern($);
mp.publicMethod();
});
If you want to be able to do that you need to declare the 'public' function like you would a private function, and then expose it as public. Like this:
$(function() {
var modulePattern = (function($) {
var privateMethod = function() {
appendText("called privateMethod()");
publicAlert();
};
var appendText = function(text) {
var text2 = $('#output').text() + " | " + text;
$('#output').text(text2);
};
var publicAlert = function(){
alert("publicAlert");
};
return {
publicMethod: function() {
appendText("called publicMethod()");
privateMethod();
},
publicAlert: publicAlert
};
});
mp = new modulePattern($);
mp.publicMethod();
});
[Edit]
I would also encourage you to get into the habit of clicking on the 'jslint' button at the top of jsfiddle, your code was missing a few semicolons, and you also redeclared the 'text' variable inside your appendText function (it was already passed in)
Also, you're using the module pattern in a slightly different way to how I've learned it. Do you have a link to your reference material?
This is how I would have done the module pattern as I know it: http://jsfiddle.net/sVxvz/
[/Edit]
Also, if you use the module pattern correctly, you can refer to the public functions by using the module name, like this:
var testModule = (function($) {
var privateMethod = function() {
appendText("called privateMethod()");
testModule.publicAlert();
};
var appendText = function(text) {
var text2 = $('#output').text() + " | " + text;
$('#output').text(text2);
};
return {
publicMethod: function() {
appendText("called publicMethod()");
privateMethod();
},
publicAlert: function() {
alert("publicAlert");
}
};
}(jQuery));
$(function() {
testModule.publicMethod();
});
But I don't really like this because the public methods can be overwritten.
someone could go testModule.publicAlert = function(){EVIL CODE OF DOOM;}; and your internal workings will happily execute it.
I understand this is a little bit different from the module pattern, but I think it still offers the same benefits of encapsulation. Public methods are declared as:
this.methodName = function(){...}
the variable $this is assigned to the current instance (this), so you can use it from within private (or public) methods to access any methods or attributes on that instance.
Fork:
http://jsfiddle.net/FNjJq/

Nested class in javascript, inheritance of private methods

i'm quite a newbie in javascript, and i'm spending some time trying to create namespaced objects in js.
Now, that's what i'm trying to do:
MainObject = function() {
var privateVariable = "i'm private";
var privateMethod = function() {
// doSomething
}
this.publicMethod = function() {
// doPublicSomething
}
}
MainObject.prototype.nested = function() {
this.publicNestedMethod = function() {
// that's not working at all
this.privateMethod(privateVariable);
}
}
MyObject = new MainObject();
MyObject.publicMethod();
MyObject.publicNestedMethod();
I tried to include the nested class inside the first one, but it's not working also if i try:
this.nested = function() {
var mainObject = this;
return {
publicNestedMethod = function() {
mainObject.privateMethod();
}
}
}();
Someone can help me please? i'm gonna loose my mind on this.
Phaedra.
Closures are a lexical feature, not a semantic one. If the object is outside the lexical scope of another, it can no longer be "nested" and access the former's local variables. In the code of your nested function/class, there's no such thing as this.privateMethod, because privateMethod is never made to be a property of MainObject. It's simply a local variable inside a function.
There's no such things as "private properties", "private methods" or "private members" in JavaScript. Hell, there's no such thing as a "class". Some people like to emulate private members using local variables as above, but doing so results in cases like this, where the discrepancy between the two concepts comes and bites one in the behind.
To conclude, it is a bad idea to write Java code, with all its OO techniques in JS, just as it is a bad idea to write C code, with all its pointers and unbounded buffers, in C#. Sure, in both cases you can do it, but you would be failing to appreciate and exploit the language's features this way.
And now that I'm done with the rant, you can do something like this to get "namespaced" functions:
MainObject = function() {
var privateVariable = "I'm private";
var privateMethod = function() {
alert('Private');
}
this.publicMethod = function() {
alert('Public');
}
this.nested = {
publicNestedMethod: function() {
privateMethod();
}
};
// or
this.nested = (function() {
var nestedPrivate = 5;
return {
publicNestedMethod: function() {
alert(nestedPrivate);
privateMethod();
}
};
})();
}
MyObject = new MainObject();
MyObject.publicMethod();
MyObject.nested.publicNestedMethod();​
Using the convention of underscore for "private" methods is a reasonable way to keep things organized.
MainObject = function() {
this._privateVariable = "i'm private";
this._privateMethod = function() {
// doSomething
}
this.publicMethod = function() {
// doPublicSomething
}
}
Well to provide the benefit of prototypal inheritance where all "subclasses" share a single instance of the method in prototype, but to ALSO provide the feature of inheriting private instances...
I came up with:
function Person(name,latentPower){
var privatesForChildren = { password:"xyz"
,latentPower:"invisibility"}
this.inherit = function(){
for(v in privatesForChildren){
eval("var " + v + "=privatesForChildren['" + v + "'];");
}
}
this.name = name;
this.revealName = function(){ alert("My name is" + this.name + "."); }
this.revealPowers = function(){ alert("I'm normal."); }
}
function Mutant(name,latentPower,fuel){
this.inherit.call(this); // Inherit private instance variables
var fuel = fuel;
this.name = name;
this.revealPowers = function(){
alert("I manifest the powers of " + latentPower + " when I " + fuel + ".");
}
}
Mutant.prototype = new Person;
Mutant.prototype.constructor = Mutant;
bob = new Person("Bob","telekenesis");
jim = new Mutant("Jim","nausea","eat pizza");
buford = new Mutant("Buford","Teflon Man","breathe");
jim.revealName(); //Inherited properly from prototype
bob.revealPowers();
jim.revealPowers();
buford.revealPowers(); //distinct from Jim's so is an "instance var"
alert(bob.latentPower); //returns undefined
alert(buford.latentPower); //returns undefined, so is "private".
How useful is that?
JavaScript Classes and Inheritance (ES6)
According to ES6, you can use JavaScript classes and inheritance to accomplish what you need.
JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript's existing prototype-based inheritance.
Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
I'm showing the examples below with variables, but it can be applied also to functions.
Inheritance (1st Approach)
This solution can only be used with getters for your private variables, otherwise your subclass will not get access to them.
class Main {
constructor() {
let privateVariable = "private";
this.publicVariable = "public";
this.getPrivateVariable = () => {
return privateVariable;
}
}
}
Main.Sub = class Sub extends Main {
getAllVariables() {
return this.publicVariable + "-" + this.getPrivateVariable();
}
}
// Testing...
let main = new Main();
let sub = new Main.Sub();
console.log(main.privateVariable); // undefined
console.log(main.publicVariable); // "public"
console.log(sub.privateVariable); // undefined
console.log(sub.publicVariable); // "public"
console.log(main.getPrivateVariable()); // "private"
console.log(sub.getPrivateVariable()); // "private"
console.log(sub.getAllVariables()) // "public-private"
Nesting (2nd Approach)
Maybe this solution is better for you because it doesn't expose your private variables outside the Main and Nested classes.
class Main {
constructor() {
let privateVariable = "private";
this.publicVariable = "public";
Main.Nested = class Nested extends Main {
getAllVariables() {
return this.publicVariable + "-" + privateVariable;
}
}
}
}
// Testing...
let main = new Main();
let nested = new Main.Nested();
console.log(main.privateVariable); // undefined
console.log(main.publicVariable); // "public"
console.log(nested.privateVariable); // undefined
console.log(nested.publicVariable); // "public"
console.log(main.getPrivateVariable); // undefined
console.log(nested.getPrivateVariable); // undefined
console.log(nested.getAllVariables()) // "public-private"
What OO system lets you inherit private methods? Part of being private is being unaccessible from other objects.
In JS in particular, "private members" are really just local variables of the function where they are declared. JS doesn't have typical OO notions of "class", "inheritance", "public", and "private", so you can't expect to copy your OOP techniques verbatim from other OOP languages.
It is a convention. You can imitate OO Java techniques like private members but that's not recommended. You can imitate in this way:
MyFunction = function(options){
var private = {};
//to reference MyFunction as a context
var that = this;
function privateFunctionThatCallPublicMethod(){
that.publicFunction("hello");
}
this.publicFunction = function(params){
alert(params + " " + private);
}
...
}
var instance = new MyFunction({oneOption:'fsdfsad'});
This is the bests approach i found to emulate OO Java Techniques...
But there is a problem, is very inefficient...
You must use prototype instead, because otherwise it would create one object per function per instance of the "class".
MyFunction = function(options){
this._private = {};
}
MyFunction.prototype._privateFunctionThatCallPublicMethod = function(){
this.publicFunction("hello");
}
MyFunction.prototype.publicFunction = function(params){
alert(params + " " + this._private);
}
Like you think private members are (in this way) a convention.
Also, there is another thing you must know...
When you pass a function of an object as a parameter to another function you must bind the context of the function...
function bind(fnThis, fn) {
return function(){
return fn.apply(fnThis, arguments);
};
}
function makeSomething(callback){
callback("hello");
}
var instance = new MyFunction();
makeSomething(bind(instance, instance.publicFunction));
This is because you must bind "this" as instance in the body of the publicFunction, otherwise is gonna be "window" instead.

Categories