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
}());
tagIdyou're accessing is public, not private =>this.tagId = id