◆ WeakMap もできたしプライベート変数とメソッドはこの方法にすることにしました
◆ 後から拡張できないのは諦める 

!function (){
    // private 変数管理用
    // 関数もインスタンスごとに作りたいならこっちいれる

    var map = new WeakMap()

    function A(val1, val2){
        this.pub_val = val1
        map.set(this, {pri_val: val2})
    }

    A.prototype.print = function(){
        var val2 = map.get(this).pri_val
        console.log(this.pub_val, val2, privateMethod(this, val2))
    }

    function privateMethod(thls, val){
        return thls.pub_val * val
    }

    window.A = window.A || A
}()

var a = new A(5, 8)
console.log(a)
// A { }
//   pub_val : 5


a.print()
// 5 8 40

console.log しても pub_val しか見えていないです

private method

まずプライベートメソッドです

普通に prototype に追加すると外から見えてしまいます
なので 関数定義全体を関数に囲んでクロージャの中に プライベートメソッドを配置します

プライベートメソッドは this の中にはいないので 呼び出すときには this を使いません
その分 インスタンスを特定するために this を渡す必要があります

this っぽく thls と書いてますが普通に self とかにすればどこかの言語でみたような感じになるので あまり気にせず使えると思います

パブリックメソッドは 呼び出し時に this. をつけて引数に this をわたさなくていいです
プライベートメソッドは呼び出し時に this. がいらないですが 引数に this をわたさないといけません

使い方が違うのがちょっと気になりますが わざわざプライベートにしたい部分はそこまで多くないと思いますし 気をつければミスもそんなにないと思います

private variable

プライベート変数はメソッドと同じ方法は使えません
メソッドは共有していていいのですが 変数は共有すると一つ書き換えると全部のインスタンスの値が変わってしまうので それぞれインスタンスごとに保存する必要があります

Map を使って インスタンスのオブジェクトに対してプライベート変数を保持するオブジェクトを保存しておきます
map.get(this) でそのオブジェクトを取り出して このオブジェクトを読み書きします

クロージャの中で作られたものなので外側から見えなく プライベートなものになります
インスタンスをキーにしているのでインスタンスごとに別のオブジェクトを保存できます

Map じゃなくて WeakMap にしているので他のインスタンスのプライベート変数を除いたりできませんし インスタンスが GC で消えると プライベート変数も GC で消してくれます
Map だと自分で消さないとずっと残ってメモリリークになります


メソッドだけどインスタンスごとに持ちたいなら こっちの WeakMap に入れてるオブジェクトに保存しておけばいいです
逆に 全インスタンスで共有したい変数なら メソッドのようにクロージャの中に直接置いておけばいいです

デメリット

特に問題なさそうに見えますが 問題点もあります

JavaScript らしく後から拡張しようとしたときに クロージャのスコープにアクセスできないので同時に作ったものしかプライベート変数が共有されません

完全にプライベートとならなくてもいいなら プライベートメソッドをオブジェクトにまとめたものと map を関数のプロパティにもたせることで共有できます
!function (){
    var method = {}
    var map = new WeakMap()

    function A(val1, val2){
        this.pub_val = val1
        map.set(this, {pri_val: val2})
    }

    A.prototype.print = function(){
        var val2 = map.get(this).pri_val
        console.log(this.pub_val, val2, method.privateMethod(this, val2))
    }

    method.privateMethod = function(thls, val){
        return thls.pub_val * val
    }

A.__privates__ = {map, method}
    window.A = window.A || A
}()


あと 継承したときにも見れません
protected じゃなくて private なので見えないほうが正しいはず