2

これはおそらく最も安全な方法です (ケース A ):

var myClass = function() { };
myClass.prototype = {
    doSomething : function() { alert('Something'); }
};

これは別の方法です (ケース B ):

var myClass = function() {
    this.doSomething = function() { alert('Something'); };
};

ケース B に示すようにこれを行うと、doSomething がメンバーになり、インスタンス化する myClass オブジェクトごとに関数が 1 回定義され、100 インスタンスのメモリに 100 回存在するという印象を受けます。ケース A 関数はメモリ内の 1 つの場所にのみ存在し、異なるインスタンスはプロトタイプを参照するだけです。

私はこれを正しく理解していますか?

おまけの質問として: ケース B のように実行すると、クロム開発者は doSomething のインテリセンスを提供しますが、それを表示するには、インスタンスの __proto__ を展開する必要があります。オブジェクト自体に表示されないのはなぜですか?つまり、プロトタイプ メンバーがオブジェクトに表示されないのに、__proto__ でスタックしてしまうのはなぜでしょうか? __proto__ スタックがフラット化されて、オブジェクトに直接表示されるようになればよかったのにと思います。これを可能にする別のケースはありますか?

4

2 に答える 2

4

まず、ケース B では、インスタンスにアタッチするのではなく、グローバル関数を作成するだけです。あなたが意味したのは:

this.doSomething = function() { }

第二に、最初のほうが速くなります。今はリンクを見つけることができませんが、jQuery honcho John Resig がこれに関する詳細なブログ投稿を行い、メソッドのプロトタイプ継承とインスタンスで宣言されたメソッドの速度テストを示しています。継承は著しく高速でした。

精神に関して言えば、私は常に継承を大いに支持してきました。これは、再利用可能なクロスインスタンス機能の場所です。それを各インスタンスに追加することには、コンストラクター内の単一の便利なクロージャー内でメソッドを宣言できるという唯一の利点がありますが、それだけです。

これがパターン B を好む理由である場合は、a) メソッドを継承しながらこれを行うことができます。b) インスタンス化のたびにそれらを再宣言しない。

function SomeClass() {
    if (!SomeClass.prototype.someMethod) {
        SomeClass.prototype.someMethod = function() {}
    }
}

ただし、これはプロトタイプのセットアップを担当するため、最初のインスタンス化が少し遅くなります。実際にはインスタンス化プロセスの仕事ではありません。

2 つのケース間で注意すべきプログラム上の違いもあります。

 function SomeClass(name) {}
 SomeClass.prototype.someMethod = function() {};
 var instance = new SomeClass();
 console.log(!!instance.someMethod); //true
 console.log(instance.hasOwnProperty('someMethod')); //false

メソッドはインスタンスによって所有されているのではなく、継承されているため、最後の行は false です。パターン B では、これは true に解決されます。

于 2012-08-14T08:23:17.800 に答える
2
  1. 正解: プロトタイプでメソッドを定義すると、1 つの関数オブジェクトが作成され、すべてのインスタンスがその 1 つの関数を参照します。コンストラクターで定義すると、インスタンスごとに新しい関数が作成されます

  2. コードにはいくつかの作業が必要です。コンストラクターを定義する方法では、doSomething関数はそれに対抗するグローバルな追加として定義されます。varただし、これはまだプロパティとして設定されていませんdoSomething。コンストラクター (クロージャー) のスコープ内で宣言された単なる関数です。これが、インスタンスにメソッドとして表示されない理由です。関数は にアタッチされていませんがthis、この問題をそのように修正しても、インスタンスごとに新しい関数オブジェクトを作成しています。


 function MyConstructor()//capitalize constructors - conventions are important
 {
     var someMethod = function(){/*..*/};
     this.someMethod = someMethod;
 }

Utkanos は、継承とプロトタイプ メソッドの意味が何であるかを指摘し ( .hasOwnProperty)、その点で彼は完全に正しい (+1)。hasOwnPropertyメソッドが false を返すことは些細なことだということを付け加えたいと思います。一般的に言えば、オブジェクトを繰り返し処理し、設定されているプロパティとメソッドと設定されていないプロパティとメソッドを確認するとき。ほとんどの場合、必要なのはメソッドではなくプロパティです。したがって、実際にはプロトタイプ レベルで設定する方が適切です。

for(var name in obj)
{
    if (obj.hasOwnProperty(name))
    {
        //do stuff, here the methods are set @ prototype level
    }
    if (obj.hasOwnPrototype(name) && typeof obj[name] !== 'function')
    {
        //same stuff, but requires extra check when methods are assigned by constructor
    }
}
于 2012-08-14T08:24:03.760 に答える