Crockford's method is probably the one I encounter the most. Frankly, it makes me pretty sad, because it is messy, semantically awful -- your constructor code is intermingled with your class definition! --, and if I recall my previous testing, inefficient.
I don't think I've ever seen the second style you describe in the wild. It also doesn't leave me very comfortable, for similar reasons to the first. Not to mention that returning from a constructor is a fairly obscure behaviour, that is likely to confuse many.
The style I favour is one of "contractual" privates, or perhaps more accurately, favouring "protected" members. A reasonably good example from myself can be found here.
A relevant subset of the code being:
var gk = (function(gk){
//static/constant members would be vars here, if I had them.
function List(collection){
this._dummy = {};
this._dummy.next = this._dummy;
this._dummy.prev = this._dummy;
this.length = 0;
if(collection){
this.addAll(collection);
}
}
List.prototype = new gk.Collection();
//stuff...
List.prototype.pushBack = function(item){
var curNode = this._dummy;
var newNode = {};
newNode.item = item;
this._add(curNode, newNode);
}
List.prototype.add = List.prototype.pushBack;
List.prototype._add = function(curNode, newNode){
newNode.prev = curNode.prev;
curNode.prev.next = newNode;
newNode.next = curNode;
curNode.prev = newNode;
++this.length;
this._registerAddition(curNode.item); //inherited from the superclass!
}
//stuff...
gk.List = List;
return gk;
})(gk || {});
All public and "private" members are attached to this
or the prototype, but anything intended to be "implementation specific" is prefixed with an underscore. This indicates that it is not a publicly guaranteed API, and to refer to it would instantly tightly couple you with the implementation. This is great if you intend to have a publicly accessible object that can expose its internals to things that need them (such as my LinkedList, which is used internally by other data structures which may need more control, but is still a perfectly valid data structure on its own).
As an added benefit, the resulting code is (in my opinion) clean, maintainable, semantic, and members are uniformly accessed regardless of their "security". It is also much easier to refactor something to/from public/private status, as you just add/remove an underscore. You also get the full benefits of the prototype chain (abstract protected members for use by the super class!). As a consequence there seems to be a bit less overhead per instance (no tests on hand, sorry), if you care about that kind of thing.
I long ago gave up on trying to make JS into a perfect clone of Java/C++/C#. It's a different language. In my opinion, you might as well just make development easier on yourself, and make clean, readable, maintainable, and usable code, instead of creating frustrating monstrosities that ape other languages based on the glory of closures. Yes, you can do just about anything with a closure, but dear god that doesn't mean you should.