2013-07-15 6 views
10

私はクロージャを使用して、プライベートメソッドとパブリックメソッドを持つオブジェクトを作成しています。 -JavaScriptでプライベート関数を継承できますか?

var Dog = (function() { 
    function Dog() {} 

    var size = 'big'; 

    var _privateSaySize = function() { 
     return 'I am a ' + size + ' dog.'; 
    } 

    Dog.prototype.publicSaySize = function() { 
     return _privateSaySize(); 
    } 

    return Dog; 
})(); 

私はプライベートな機能しか持たず、別のオブジェクトに継承されているオブジェクトを持っていたいと思います。しかし、これはJavaScriptで可能ですか?

+1

この関数は何ですか?Dog =(function(){})() '? – Amberlamps

+2

'private'メンバは、OOPをサポートする_any_言語で定義されているクラス内で_only_で表示されます。私はあなたがしようとしているものを手に入れません。 – Leri

+0

一般的にはありませんが、あなたの「私的関数」は 'notSoPrivateSaySize = new Dog()で簡単にアクセスできます。publicSaySize(); ' – Bergi

答えて

1

別のインスタンスのプライベート状態を継承したい場合はありますか? JavaScriptでこれを行うことができます。次のように今、私たちは私たちの基本クラスを作成することができます

function weakBind(functable, prototype, state) { 
    return function() { 
     return functable.apply(this, Object.getPrototypeOf(this) === prototype ? 
      [state].concat(Array.prototype.slice.call(arguments)) : arguments); 
    }; 
} 

:まず、効用関数を定義する必要が

var Dog = (function() { 
    function Dog() { 
     if (this instanceof Dog) { 
      // constructor code 
     } else return Object.create(private); 
    } 

    var public = Dog.prototype, private = Object.create(public, { 
     size: { 
      value: "big" 
     } 
    }); 

    public.saySize = weakBind(function (private) { 
     return "I am a " + private.size + " dog."; 
    }, public, private); 

    return Dog; 
}()); 

次のように今、あなたは犬を作成することができます。

var dog = new Dog; 
alert(dog.saySize()); // I am a big dog. 
alert(dog.size);  // undefined 

私たちは、次のようにプライベート状態を継承できます。

var Chihuahua = (function() { 
    function Chihuahua() { 
     Dog.call(this); 
    } 

    var private = Dog(); 

    Object.defineProperty(private, { 
     size: { 
      value: "small" 
     } 
    }); 

    var public = Chihuahua.prototype = Object.create(Dog.prototype); 

    public.saySize = weakBind(public.saySize, public, private); 

    return Chihuahua; 
}()); 

次のように今、あなたはチワワを作成することができます。

var chi = new Chihuahua; 
alert(chi.saySize()); // I am a small dog. 
alert(chi.size);   // undefined 

デモを参照してください:http://jsfiddle.net/b3Eyn/

注:を私はちょうどそれがJavaScriptでプライベート状態を継承することは可能だということを示すために、この答えを書きました。しかし、私はあなたにこのパターンを使わないことを勧めます。あなたのコードをうまく設計すれば、まずはプライベートな状態を継承する必要はありません。

8

いいえ、できません。

JavaScriptの継承はプロトタイプベースなので、プロトタイプのメソッドだけを「拡張」することができます。

+0

合意。多くのJS開発者は、公開されているメソッドの先頭にアンダースコアを付けて、保護されているか、そうでなければパブリックAPIの一部ではないことを知らせるだけで妥協することはありません。開発者は希望により変更することもできますが、それはそれぞれのリスクです。正直言って、JSで公開されているオブジェクトを保護しようとするのは、あなたのライブラリを使用する人が公共の機能を上書きしたり、共有オブジェクト/プロトタイプをスクランブルするだけなので、かなり無駄な努力です。 それは頭痛の価値があるとは思われません。 –

2

種類... Bergiが指摘しているように、アクセスはスコープで定義されているため、親のすぐ内側に継承者を定義すれば、おおよそのものを得ることができます。

var BarkingDog; 
var Dog = (function() { 
    function Dog() {} 

    var size = 'big'; 

    var _privateSaySize = function() { 
     return 'I am a ' + size + ' dog.'; 
    }; 

    Dog.prototype.publicSaySize = function() { 
     return _privateSaySize(); 
    }; 

    BarkingDog = (function() { 
     function BarkingDog() {} 

     var say = 'woof'; 

     BarkingDog.prototype = new Dog(); 

     BarkingDog.prototype.bark = function() { 
      return _privateSaySize() + ' ' + say; 
     }; 

     return BarkingDog; 

    })(); 

    return Dog; 
})(); 

var myDog = new BarkingDog(); 
console.log(myDog.bark()); 
console.log(myDog.publicSaySize()); 

あなたがが...したいと思う理由はわからない:D JavaScriptで

5

変数(関数)のプライバシーが関数のスコープを介して行われます。クロージャスコープからエクスポートされた場合にのみ、外部からアクセスできます。他の方法はありません。

メソッドがプライベート関数にアクセスできるオブジェクトを作成するには、同じスコープに配置するだけです。オブジェクトが他のオブジェクトから継承するオブジェクトであるかどうかは、まったく関係ありません。

function Dog() {} 
function Dalmatian() {} 
Dalmation.prototype = Object.create(Dog.prototype); 
Dalmation.prototype.size = "big"; 
function Dackel() {} 
Dackel.prototype = Object.create(Dog.prototype); 
Dackel.prototype.size = "small"; 

(function() { 
    // private function 
    function say(s) { 
     console.log("I'm a "+s+" dog"); 
    } 
    // both accessible from the Dog and Dackel public methods 
    Dog.prototype.saySize = function() { 
     say(this.size || "normal"); 
    }; 
    Dackel.prototype.saySize = function() { 
     say(this.size + " but loud"); 
    }; 
})(); 
new Dog().saySize(); 
new Dalmatian().saySize(); 
new Dackel().saySize(); 
0

ドット表記の使用を避けることができます。しかし、それは本当にプライベートではありません。

var Dog = (function() { 
    function Dog() {} 

    var size = 'big'; 

    Dog.prototype['-privateSaySize'] = function() { 
     return 'I am a ' + size + ' dog.'; 
    } 

    Dog.prototype.publicSaySize = function() { 
     return this['-privateSaySize'](); 
    } 

    return Dog; 
})() 
+0

プロパティの「内部性」を示すために、アンダースコア「_」がマイナスではなく使用されます。そうすれば、大括弧表記を避けることができます。 – Bergi

+0

@Bergiそれがポイントです。私はマイナス記号を使用しました。なぜならあなたはドット表記法を使うことができないので、それは括弧表記を使うだけです。 – boskop

+0

それはどのように役立ちますか?プライバシーを示すための[慣習](http://stackoverflow.com/q/4484424/1048572)ブラケット記法は何も変更しません。 – Bergi

関連する問題