53

財産とは何ですかprototype、なぜそれが必要なのですか?prototypeこれまでのところ、これにより、オブジェクトのより本質的でプライベートなものへのパブリックアクセスが提供されることを学びました。あれは正しいですか?

また、次のステートメントの違いは何ですか?

MyConstructor.age = 30;
MyConstructor.prototype.age = 30;

要するに、私はキーワードのより良い理解が必要ですprototype

ありがとう

4

3 に答える 3

66

「プロトタイプ」は、オブジェクトで役割を果たすものです。

Javascriptでは、すべてがオブジェクトです。すべてのオブジェクトには種類があり、したがってprototypeその種類を継承します。

たとえば、単純な配列を考えてみましょうvar a = []。のように、それを使って操作を行うことができますa.push(10)。このpush方法はどこから来たのですか?Arrayオブジェクトのプロトタイプからaです。

Arrayオブジェクトでメソッドを定義するだけで、オブジェクトに独自のメソッドを追加できますprototype。例えば:

Array.prototype.sortNum = function() {this.sort(function(a, b) {return a - b});};

このようにして、メソッドを定義する前に作成された配列も含め、すべてのa.sortNum()配列で同じようなことを行うことができます。sortNum

(注:互換性の理由から、通常、sのようなネイティブオブジェクトのプロトタイプを拡張することはお勧めしません。ただし、この特定の例は、通常、古いブラウザーのような正規化メソッドとArray同様に、歓迎すべき追加です。)mapforEach

決して拡張しないでください!ステートメント、演算子、およびこれらの種類のケースObject.prototypeを台無しにすることを気にしない限り。)for...inin

名前MyConstructorが示すように、独自のクラスprototypeを定義する場合は、そのクラスのすべてのインスタンスのメソッドを定義するために、そのクラスを定義する必要があります。

function MyConstructor(name) {this.name = name};
MyConstructor.prototype = {
    print: function() {return this.name;}
};

var mc = new MyConstructor("foo");
alert(mc.print()); // alerts "foo"

prototypesで関数だけでなく、次のように定義することもできます。

MyConstructor.prototype.age = 30;

alert(mc.age); // alerts 30

これを行って「デフォルト」のオブジェクト値を定義する場合は注意が必要です。これを変更すると、そのクラスのすべてのインスタンスが変更される可能性があるためです。

しかし、これは便利Object.definePropertyです:

Object.defineProperty(MyConstructor.prototype, "wholeString", {
    get: function() {return this.name + "=" + this.age;},
    set: function(v) {this.name = v.substring(3);}
});

alert(mc.wholeString); // alerts "foo = 30"

(残念ながら、IE <9ではこれはDOMオブジェクトに対してのみ許可されます...)

代わりに定義する場合MyConstructor.age = 30、実際に行っているのは関数 MyConstructorのメンバーを定義することなので、mc.age未定義になります。のすべてのインスタンスは、関数のものではなく、でMyConstructor定義されたメソッドとメンバーを継承します。MyConstructor.prototypeMyConstructor

実際、言うことはもっとたくさんあります。オブジェクトは別のクラスのサブクラスである可能性があるためprototype、スーパークラスのを継承することもできます。たとえばdocument.body、はのインスタンスですHTMLBodyElement。これは、のサブクラスでありHTMLElement、のサブクラスでElementあり、などのように、最上位のスーパークラスとして取得Objectされるまで続きます。したがって、、、、およびのプロトタイプでdocument.body定義されたすべてのメソッドを継承します。これはプロトタイプチェーンと呼ばれます。HTMLBodyElementHTMLElementElementObject

カスタムオブジェクトで同じことを行うのは少し注意が必要です。

function Class() {};
Class.prototype.foo = function() {alert("foo");};

function Subclass() {};
Subclass.prototype = new Class();
Subclass.prototype.bar = function() {alert("bar");};

var a = new Class(), b = new Subclass();
a.foo(); // alerts"foo"
a.bar(); // throws an error
b.foo(); // alerts "foo"
b.bar(); // alerts "bar"

a instanceof Class;    // true
a instanceof Subclass; // false
b instanceof Class;    // true
b instanceof Subclass; // true
于 2012-08-21T23:07:17.577 に答える
6

JavaScriptでは、関数オブジェクトには組み込みの.prototypeプロパティがあります。このプロパティの値はオブジェクトです。関数がコンストラクターとして使用される場合、結果のインスタンスはその「プロトタイプ」オブジェクトから継承します。

例:

var Dog = function () {}; // the constructor function

Dog.prototype.bark = function () {}; // adding a method to Dog.prototype

var dog1 = new Dog; // creating a new instance

dog1.bark(); // the instance inherits the "bark" method from Dog.prototype

(関数オブジェクトの)プロパティは内部プロパティ.prototypeと同じではないことに注意してください。[[Prototype]]すべてのオブジェクトには後者が含まれています。これは、オブジェクトのプロトタイプへの内部参照です。(上記の例では、dog1オブジェクト[[Prototype]]はを参照していDog.prototypeます。)一方、組み込み.prototypeプロパティを持つのは関数オブジェクトのみです(コンストラクターとして使用できるのは関数オブジェクトのみであるため、これは理にかなっています)。

于 2012-08-21T22:50:22.353 に答える
4
var foo = function () {};
foo.bar = 5;
foo.prototype.foobar = 10;

var x = new foo();
x.bar; // undefined
x.foobar; // 10

編集:また、あなたはそれからすることができます

foo.prototype.foobar = 20;
x.foobar; // 20
于 2012-08-21T22:56:15.347 に答える