1. Первая конструкция
хуже второй - в ней, вместе с прототипом, переопределяется свойство
constructor, на которое, обычно, наплевать, но иногда оно может помочь определить конструктор инстанса.
2.
_private ни капли не приват без
var.
3. Это IIFE, а не конструктор - вызывается без
new, одноразовая фабрика. Минусы - по сравнению с чем?
UPD: Я так понимаю, вам хочется приватных данных и функций у инстансов. Верните конструктор из замыкания. Примерно так:
var Test = function(){
function Test(privateData, publicData){
this.publicData = publicData;
this.instanceFn = function(){
console.log('Публичный метод инстанса');
privateFn(privateData);
}
}
Test.prototype.protoFn = function(data){
console.log('Публичный метод прототипа');
privateFn(this.publicData);
}
function privateFn(data){
console.log('Приватная функция:', data);
}
return Test;
}()
var test = new Test('Приватные данные', 'Публичные данные');
console.log(test.publicData); // => Публичные данные
test.instanceFn(); // => Публичный метод инстанса, Приватная функция: Приватные данные
test.protoFn(); // => Публичный метод прототипа, Приватная функция: Публичные данные
Минус - методы инстанса, работающие с приватными данными, создаются каждый раз при вызове конструктора. В ES5 иначе никак, разве что публичные "приватные" свойства, что якобы не замечаем. В ES6 с приватными данными полегче - есть Symbol и WeakMap.