最初の例では、そのコンストラクターで作成された新しいオブジェクトごとに新しい関数オブジェクトを作成し、それをプロパティに割り当てます。2 番目の例では、各新しいオブジェクトが参照する単一の関数を作成します。
これは、たとえば最初の例の場合
var fooObj1 = new Foo();
var fooObj2 = new Foo();
alert(fooObj1.bar === fooObj2.bar) //false
しばらくの間
alert(fooObj1.bar === fooObj2.bar) //true
これは、最初の例ではバーのプロパティが 2 つの別個の同一のオブジェクトを参照しているのに対し、2 番目の例ではそれらが同じであるためです。
一般に、そのコンストラクターで作成されたすべてのオブジェクト間で共有される「静的」オブジェクトを宣言する場合を除き、関数はプロトタイプで宣言してメモリを保持する必要がありますが、他のオブジェクトは個別に宣言する必要があります。
関数よりも通常のオブジェクトや配列との違いがわかりやすい
function Foo(){
this.bar = [];
}
var fooObj1 = new Foo();
var fooObj2 = new Foo();
fooObj1.bar.push("x");
alert(fooObj2.bar) //[]
とは対照的に:
function Foo(){
}
Foo.prototype.bar = []
var fooObj1 = new Foo();
var fooObj2 = new Foo();
fooObj1.bar.push("x");
alert(fooObj2.bar) //["x"]