28

関数を宣言すると、そのプロトタイプのコンストラクター プロパティが関数自体を指すようになるため、次のように関数のプロトタイプを上書きするのは悪い習慣ですか?

function LolCat() {
}

// at this point LolCat.prototype.constructor === LolCat

LolCat.prototype = {
    hello: function () {
        alert('meow!');
    }
    // other method declarations go here as well
};

// But now LolCat.prototype.constructor no longer points to LolCat function itself

var cat = new LolCat();

cat.hello(); // alerts 'meow!', as expected

cat instanceof LolCat // returns true, as expected

これは私のやり方ではありませんが、私はまだ次のアプローチを好みます

LolCat.prototype.hello = function () { ... }

しかし、私は他の人がこれをしているのをよく見かけます。

最初の例のように、利便性のために関数のプロトタイプ オブジェクトを上書きして、プロトタイプからコンストラクタ参照を削除することによって、何らかの影響や欠点がありますか?

4

6 に答える 6

23

これに関する限り、ベスト プラクティスについて言及している人は見当たりません。そのため、constructorプロパティが有用であることがわかるかどうかにかかっていると思います。

注目すべきことの 1 つは、constructorプロパティを破棄しない場合、作成されたオブジェクトでもプロパティを使用できることです。それは役に立つかもしれないように私には思えます:

var ClassOne = function() {alert("created one");}
var ClassTwo = function() {alert("created two");}

ClassOne.prototype.aProperty = "hello world"; // preserve constructor
ClassTwo.prototype = {aProperty: "hello world"}; // destroy constructor

var objectOne = new ClassOne(); // alerts "created one"
var objectTwo = new ClassTwo(); // alerts "created two"

objectOne.constructor(); // alerts "created one" again
objectTwo.constructor(); // creates and returns an empty object instance

だから、それは建築上の決定だと私には思えます。インスタンス化された後、作成されたオブジェクトがそのコンストラクターを再呼び出しできるようにしますか? その場合は保管してください。そうでない場合は、それを破壊します。

objectTwo のコンストラクターは、標準の Object コンストラクター関数とまったく同じになり、役に立たないことに注意してください。

objectTwo.constructor === Object; // true

したがって、呼び出しnew objectTwo.constructor()は と同等new Object()です。

于 2012-09-04T09:42:02.407 に答える
6

それは悪い習慣ではありませんが、自分が何をしているのか、そしてその理由を知る必要があります。これは、プロトタイプの継承に非常に役立ちます。プロトタイプを上書きするオブジェクトは、そのプロトタイプに割り当てたオブジェクトのすべてのプロパティを取得します。

を使用してオブジェクトを継承させます

ChildClassName.prototype = new ParentClass();.

現在、ChildClassName は ParentClass のすべての機能を備えていますが、以前にそのプロトタイプに割り当てられていた機能はすべて失われています。を使用してオブジェクトのコンストラクター プロパティをリセットすることを忘れないでください。

ChildClassName.prototype.constructor=ChildClassName. 

それ以外の場合、オブジェクトは (オブジェクトの型をテストするときに) ChildClassName 型ではなく ParentClass 型であると報告されます。

これで、自分で説明した方法で ChildClassName オブジェクトにさらにメソッドを追加できるようになりました。

ChildClassName.prototype.myMethod = function(){
    //do stuff
}

結果は、親オブジェクト/「クラス」(もちろん JavaScript には実際のクラスはありません) と、それを継承してその機能を拡張する子オブジェクト/「クラス」です。

プロトタイプを上書きすると、それに割り当てられたプロパティが失われることを知っておく必要があります。継承オブジェクトを構築するとき、これはまさにあなたが望むものかもしれません。

于 2012-09-04T09:34:19.077 に答える
3

この形:

LolCat.prototype = {
  hello: function () {
      alert('meow!');
  }
};

既存のメソッドとパブリック プロパティを破棄します。この例では、与えられたように、新しく作成された LolCat にはプロパティやメソッドがないため、問題ではありません。ただし、より複雑なコードではこれに注意する必要があります。

この形:

LolCat.prototype.hello = function () { ... }

新しいメソッドを既存のオブジェクトに追加し、既存のものをそのまま保持します。

于 2012-09-04T09:26:52.663 に答える
1

constructorプロトタイプの継承を使用するときに を上書きすることは悪い習慣ではありません。実際、多くの人が次のようにしています。

LolCat.prototype = {
    constructor: LolCat,
    hello: function () {
        alert('meow!');
    }
};
于 2012-09-04T09:28:13.833 に答える
1

何年にもわたる JavaScript の後、私は奇妙なバグに遭遇しました。オブジェクトの新しいインスタンスが渡され、__proto__そのprototypeクラスが次のように宣言されたときに mixin に渡されたときに失われました。

MyClass.prototype = {
   constructor: MyClass,
   myMethod(){ ...}
};

を使用する場合、もう問題はありません:

Object.assign( MyClass.prototype, {
   myMethod(){ ...}
});

おまけ: コンストラクトを再署名する必要はもうありません。

プロトタイプ プロパティを完全に上書きすると、そのスペシャル属性も消去され、通常の属性として変換されるためだと思います...おそらく、これはデフォルトで書き込み可能であってはなりません...

于 2018-06-19T13:40:01.620 に答える
0

それは悪い習慣ではありません。しかし、以下のような関数をオーバーライドする簡単で標準的な方法があります。「関数 LolCat()」をグローバルに定義すると、ウィンドウの下に作成されるので、いつでも以下のようにコーディングできます。

window.LolCat = function() {...};
LolCat.prototype.hello = function () { ... }
于 2012-09-04T09:39:18.950 に答える