1. Просто переменные в замыкании, как в Вашем примере. Из плюсов - работает везде, из минусов - переменные общие для всех инстансов
2. Просто соглашение, что определенные имена считать приватными и не трогать, общепринятым таким соглашением являются имена начинающиеся с подчеркивания _ - работает везде, но по факту ничего не делает, все на совести кодера
3. Поля символы (Symbol()) - нужен es2015+, по факту тоже не совсем приватные, из вне к ним можно доступ получить если есть доступ к символу (или сами его отдадите, или есть возможность получить все символы объекта), но уникальность символа дает достаточную приватность. Я лично предпочитаю именно этот вариант
4. объект в WeakMap с текущим this в качестве ключа - es2015+, полная приватность, но достаточно громоздко, суть в том, что в конструкторе мы создаем новый объект для хранения приватных свойств и сохраняем его в WeakMap с ключом this, а там где нужно извлекаем по this