Node.JSで「継承」をどのように使用しますか? プロトタイプは Java のインターフェースに似ていると聞きました。でも使い方がわからない!
3 に答える
純粋な JS でオブジェクト コンストラクターを作成する:
これらは、他の JS 関数と同様の関数ですが、 new キーワードで呼び出されます。
function Constructor(){ //constructors are typically capitalized
this.public = function(){ alert(private); }
var private = "Untouchable outside of this func scope.";
}
Constructor.static = function(){ alert('Callable as "Constructor.static()"'); }
var instance = new Constructor();
継承:
function SubConstructor(){
this.anotherMethod(){ alert('nothing special'); }
}
function SubConstructor.prototype = new Constructor();
var instance = new SubConstructor();
instance.public(); //alerts that private string
主な違いは、プロトタイプの継承は、オブジェクトを構築するものではなく、オブジェクトに由来することです。
欠点の 1 つは、private のようなインスタンス変数の継承を可能にする適切な方法がないことです。
しかし、途方もない巨大な利点は、スーパー コンストラクターに影響を与えずにプロトタイプをいじることができることです。オブジェクトが構築された後でも、すべてのオブジェクトのメソッドやプロパティを変更できます。これは非常に紛らわしいAPIになるため、高レベルのコードで実際に行われることはめったにありませんが、インスタンスのセット全体で変化する値を共有するだけでなく、内部のタイプのものには便利です。それはグローバルです。
このインスタンス化後の動作が得られる理由は、JS 継承が実際にはルックアップ プロセスで動作するためです。メソッド呼び出しは、呼び出されたメソッドが見つかるか終了するまで、インスタンスとそのコンストラクター プロトタイプ プロパティのチェーンを実行します。これは、カスケード継承 (アンチパターンとして広く認識されている) を完全に狂わせると、実際には遅くなる可能性があります。
私自身、特に継承のためにプロトタイプを作成することはあまりありません。代わりに、より合成されたアプローチを介してオブジェクトを構築することを好みますが、必要なときに非常に便利で、あまり明白でないユーティリティを提供します。たとえば、1 つのプロパティだけが異なる場合に役立つオブジェクトがあるが、元のプロパティには触れたくない場合などです。
var originInstance = {
originValue:'only on origin',
theOneProperty:'that would make this old object useful if it were different'
}
function Pseudoclone(){
this.theOneProperty = "which is now this value";
}
Pseudoclone.prototype = originInstance;
var newInstance = new Psuedoclone();
//accesses originInstance.originValue but its own theOneProperty
Object.create のような最新の便利なメソッドがありますが、関数コンストラクターのみがプライベート/インスタンス変数をカプセル化するオプションを提供するため、カプセル化を必要としないものは10のうち9回はオブジェクトリテラルになるため、私はそれらを好む傾向があります.
オブジェクトのオーバーライドと呼び出し順序:
( function Constructor(){
var private = "public referencing private";
this.myMethod = function(){ alert(private); }
} ).prototype = { myMethod:function(){ alert('prototype'); };
var instance = new Constructor();
instance.myMethod = function(){ alert(private); }
instance.myMethod();//"undefined"
注: コンストラクターを括弧で囲むと、コンストラクターを 1 か所で定義および評価できるため、同じ行のオブジェクトのように扱うことができます。
外部で上書きされたメソッドがコンストラクターのクロージャーの外部で定義されているため、myMethod は「未定義」を警告しています。したがって、メソッドを置き換えることはできますが、それが行ったことにはアクセスできません。
では、コメントを書いてみましょう。
( function Constructor(){
var private = "public referencing private";
this.myMethod = function(){ alert(private); }
} ).prototype = { myMethod:function(){ alert('prototype'); };
var instance = new Constructor();
//instance.myMethod = function(){ alert(private); }
instance.myMethod();//"public referencing private"
と...
( function Constructor(){
var private = "public referencing private";
//this.myMethod = function(){ alert(private); }
} ).prototype = { myMethod:function(){ alert('prototype'); };
var instance = new Constructor();
//instance.myMethod = function(){ alert(private); }
instance.myMethod();//"prototype"
同じ理由で、プロトタイプ メソッドもその内部プライベート変数にアクセスできないことに注意してください。コンストラクター自体で何かが定義されているかどうかがすべてです。コンストラクターに渡されるパラメーターは、事実上、一連のデフォルト オプションのオーバーライドなどを行うのに便利なプライベート インスタンス変数になることに注意してください。
カップル 詳細
必要なパラメーターがない限り、実際には new で呼び出すときに括弧を使用する必要はありませんが、私は習慣からそれらを残す傾向があります (それらを発火する関数と見なし、その発火の範囲を表すオブジェクトを残すようにします)。 Java開発者にとっては、new Constructor;
また、パラメーターを必要とするコンストラクターでは、次のようなデフォルト値を内部的に追加するのが好きです。
var param = param || '';
そうすれば、コンストラクターを Node の util.inherit のような便利なメソッドに渡すことができ、未定義の値によって問題が発生することはありません。
Params は、コンストラクターで定義された任意の var と同様に、実質的に非公開の永続インスタンス var です。
Oh とオブジェクト リテラル ( で定義されたオブジェクト{ key:'value' }
) は、おそらくこれとほぼ同等であると考えるのが最適です。
var instance = new Object();
instance.key = 'value';
Coffeescript の助けを借りて、はるかに簡単に実現できます。
例: クラスを拡張するには:
class Animal
constructor: (@name) ->
alive: ->
false
class Parrot extends Animal
constructor: ->
super("Parrot")
dead: ->
not @alive()
静的プロパティ:
class Animal
@find: (name) ->
Animal.find("Parrot")
インスタンス プロパティ:
class Animal
price: 5
sell: (customer) ->
animal = new Animal
animal.sell(new Customer)
サンプル コードClasses in CoffeeScriptを取り上げます。CoffeeScript の詳細については、公式サイト ( http://coffeescript.org/ ) を参照してください。