プロトタイプ継承の理解が不十分なため、行き詰っています。プロトタイプ継承とは何か、どのように実装されているのか知りたいです。
簡単な例を1つ示していただけますか?
どんな助けでも大歓迎です。
プロトタイプ継承の理解が不十分なため、行き詰っています。プロトタイプ継承とは何か、どのように実装されているのか知りたいです。
簡単な例を1つ示していただけますか?
どんな助けでも大歓迎です。
オブジェクトがあり、プロパティを検索したいとします。ここで、プロパティが存在しないと想像してください。別のオブジェクトでそのプロパティの検索を自動的に続行できるとしたら? それが基本的にプロトタイプ継承です。
したがって、唯一の問題は、オブジェクト間のこの関係をどのように作成するかです。まあ、それは奇妙な部分です。
主な歴史的な方法から始めましょう。つまり、関数を使用しています。
最初に注意すべきことは、JavaScript の関数はそれ自体がオブジェクトであるということです。独自のプロパティを持つことができ、プロトタイプの継承を使用して他のプロパティにアクセスできます。
それでは、関数を作成することから始めましょう。
function Foo() {
// our function
}
これで、 という名前の関数ができましFoo
た。新しい関数は、prototype
作成時に名前が付けられたプロパティを自動的に取得します。そのプロパティは (ほぼ) 空のオブジェクトを参照します。
console.log(typeof Foo.prototype); // object
なぜそのプロパティとオブジェクトが存在するのですか? これらは、JavaScript が上記で説明したオブジェクト間の関係を形成する奇妙な方法をサポートするために存在します。
基本的に、Foo.prototype
オブジェクトは、オブジェクトの新しいプロパティを探すときに「バックアップ」オブジェクトとして使用するものです。しかし、使用したいオブジェクトとオブジェクトの間に特別な関係はまだ形成されていませんFoo.prototype
。
これを行うには、実際にnew
演算子を使用して関数を呼び出します。
var my_object = new Foo();
そして、そこに行きます。これmy_object
が新しい空のオブジェクトです。しかし、その「プロトタイプチェーン」には、そのプロパティからFoo
離れた機能からぶら下がっているオブジェクトがあります。.prototype
つまり、 でプロパティを検索するときにmy_object
、プロパティが存在しない場合は、Foo.prototype
オブジェクトの検索を続行します。
問題は、 に役立つと思われるものを何も追加していないことですFoo.prototype
。しかし、実際にはそのオブジェクトには 1 つのプロパティがあります。Foo
このプロパティは、関数を作成したときにも自動的に作成されたもので、.constructor
プロパティです。
そのプロパティは何を参照していますか? 関数への参照がありFoo
ます。言い換えると:
Foo.prototype.constructor === Foo; // true
よし、もし私たちのmy_object
が空で、その上のプロパティを探しているときにmy_object
存在しない場合、それはFoo.prototype
オブジェクトの検索を続けFoo.prototype.constructor
ますmy_object
。
my_object.constructor === Foo; // true
そして、それは機能します。my_object
は という名前のプロパティを持っていなかったため、継承constructor
元のオブジェクトである を検索し続けました。これはFoo.prototype
、ご存知の.constructor
ように、関数を参照するプロパティを持っていFoo
ます。
素晴らしい。しかし、コード内でより便利な他のプロパティをどのように設定すればよいでしょうか? に追加するだけFoo.prototype
です。my_object
オブジェクトがそれらを直接所有していない場合、これらのプロパティを見つけることができます。
// give a custom property to `Foo.prototype`
Foo.prototype.bar = "foobar";
// see if we can access that property on your object
my_object.bar === "foobar"; // true
案の定、うまくいきました。それでは、そのプロパティFoo
にもアクセスできる新しいオブジェクトを作成できるかどうか見てみましょう。.bar
var another_object = new Foo();
another_object.bar === "foobar"; // true
繰り返しますが、機能します。これはFoo
、キーワードを使用して呼び出して作成されたすべてのオブジェクトnew
のプロトタイプ チェーンにFoo.prototype
オブジェクトが含まれるためです。つまり、Foo.prototype
はから作成されたすべてのインスタンスで共有Foo
されます。
したがって、Foo.prototype.bar
プロパティを変更すると、作成した両方のオブジェクトに反映されます。
Foo.prototype.bar = "raboof";
my_object.bar === "raboof"; // true
another_object.bar === "raboof"; // true
したがって、両方のオブジェクトが、「プロトタイプチェーン」内の次のオブジェクトに検索を渡すことによって、持っていないプロパティを探しているだけであることがわかります。これは、Foo
関数からぶら下がっている奇妙なオブジェクトです... Foo.prototype
.
このオブジェクトの関係をセットアップする新しい方法がありますが、これは元の方法であり、その奇妙さにもかかわらず、おそらく最初に理解する必要があります。
これは私がそれを理解する方法です:
これはコンストラクターと見なすことができます
var Thing = function(){
this.method1 = function(){
alert( "method 1" );
}
}
これはその例です
var a_thing = new Thing();
a_thing.method1();
これで、コンストラクターのプロトタイプに何かを追加すると、既にインスタンス化されたオブジェクトで自動的に使用できるようになります。
Thing.prototype.method2 = function(){
alert( "method2" );
}
a_thing.method2();
お役に立てれば。
これは私が考えることができる最も単純な例です。
ピザ クラスは、次の行を使用して circle から継承します。
pizza.prototype = new circle();
完全な例:
<html>
<head>
<script>
// base class
function circle(radius){
this.radius = radius;
this.getArea = function ()
{
return (this.radius * this.radius) * Math.PI;
};
this.foo = function ()
{
return "circle foo";
};
return true;
}
// child class
function pizza(flavour, radius){
circle.call(this, radius);
this.flavour = flavour;
this.foo = function ()
{
return "pizza foo";
};
return true;
}
// Inheritance
pizza.prototype = new circle();
function Go(){
// Instancing new object
var myCircle = new circle(8);
var myPizza = new pizza("Onion", 5);
// Calling property
var pizza_area = myPizza.getArea();
// Calling override foo function
var foo = myPizza.foo();
// Calling foo base class
var base = pizza.prototype.foo.call(myPizza);
//Line.prototype.someFunction.call(myLine);
var isBase = myCircle instanceof pizza;
isBase = myPizza instanceof pizza;
}
</script>
</head>
<body onload="Go();">
</body>
</html>