4

私はjavascriptを学んでいて、戸惑いました。以下の例があるここの例:-

// define the Person Class
function Person() {}

Person.prototype.walk = function(){
  alert ('I am walking!');
};
Person.prototype.sayHello = function(){
  alert ('hello');
};

// define the Student class
function Student() {
  // Call the parent constructor
  Person.call(this);// <---- Confusion
}

// inherit Person
Student.prototype = new Person(); //<---- Confusion

// correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;

// replace the sayHello method
Student.prototype.sayHello = function(){
  alert('hi, I am a student');
}

// add sayGoodBye method
Student.prototype.sayGoodBye = function(){
  alert('goodBye');
}

var student1 = new Student();
student1.sayHello();
student1.walk();
student1.sayGoodBye();

// check inheritance
alert(student1 instanceof Person); // true 
alert(student1 instanceof Student); // true

さて、私は<----この 2 行で混乱しています ( )。私が言うときPerson.call(this);、これは単に Person クラスのプロパティを継承することを述べているだけです...そうですか?

じゃあこれは何をしているの?

  // inherit Person
    Student.prototype = new Person(); //<---- Confusion

私の知る限り、.prototypeすべてのプロパティも継承しますか?

4

1 に答える 1

4

それを説明するために、まずコンストラクター関数が JavaScript でどのように機能するかを思い出しましょう。

function Guide(a) {
    this.a = a;
}
Guide.prototype.q = "Life, the Universe, and Everything";

var g = new Guide(42);
console.log(g.q); // "Life, the Universe, and Everything"
console.log(g.a); // 42

を行うnew Guide(42)と、newオペレーターは新しいオブジェクトを作成し、プロパティを使用してプロトタイプGuide.prototypeを割り当てます。次にnewを呼び出しGuide、その新しいオブジェクトを として渡しますthis。プロトタイプにない新しいオブジェクトにプロパティを追加するためにGuide使用します。thisその後、new式が完了し、その結果が作成された新しいオブジェクトになります。

を見るとg.q、オブジェクトには と呼ばれる独自のプロパティgがないため、JavaScript エンジンはのプロトタイプを調べます。これは (再び) 作成時に割り当てられます。そのプロトタイプにはプロパティがあるため、エンジンはその値を使用します。qgq

対照的に、 を見るとg.agオブジェクトには という独自のプロパティがaあるため、値が直接使用されます。

Studentその基盤が整ったら、とを見てみましょうParent

function Student() {
  // Call the parent constructor
  Person.call(this);// <---- Confusion
}

を呼び出すとnew Student()、 への呼び出し内で、Student(this再び)new演算子によって作成された新しいオブジェクトでありStudent.prototype、基礎となるプロトタイプとして持っています。しかし、Parent関数はこの新しいオブジェクトに対して何もする機会がありませんでした。したがって、その行が行うことは、以前に割り当てた関数のParentように、プロトタイプを介して行うことができない新しいオブジェクトに対して行う必要があることは何でも行う機会を与えることです。技術的に言えば、は関数を呼び出し、への呼び出し内に値が渡されるようにします(この場合、への呼び出しの 、 たとえば新しいオブジェクト)。クラスベースの言語に精通している場合、これは次のようになりますGuidethis.aParent.call(this);ParentthisParentcallthisStudentsuper();(これは Java ですが、アイデアはわかります) 派生コンストラクター内: 基本コンストラクターにオブジェクトを初期化する機会を与えます。

// inherit Person
Student.prototype = new Person(); //<---- Confusion

Studentは から継承することになっているため、Personそのコードが行っているのは、 を介して作成されたオブジェクトに割り当てられるプロトタイプを作成することですnew Student。作成しているオブジェクトはPersonオブジェクトです。

FWIW、そのコードは構築チェーンを正しく実装していません( [作成時Person呼び出されたときの両方で]必要以上に頻繁に呼び出しており、設定に失敗しています)。Student.prototype Studentconstructor

Studentprototypeプロパティを作成するより正しい方法はParent、 内から呼び出す場合Student、次のようになります。

function derive(child, parent) {
    function ctor() { this.constructor = child; }
    ctor.prototype = parent.prototype;
    child.prototype = new ctor();
}

derive(Student, Parent);

Parent.prototypeこのようにして、 を呼び出さずに に基づくプロトタイプを取得しParentます。これはどちらか一方です。 createを呼び出す、内で呼び出すかのいずれかですが、両方を実行しないでください。コンストラクター関数で階層を構築する場合、通常、子プロトタイプを作成するときではなく、子コンストラクターから親を呼び出します。オブジェクトの直接継承 (コンストラクター関数なし) を使用する場合は、もちろん逆の方法で行います。ParentStudent.prototypeParentStudent

JavaScript での継承に興味がある場合は、私が作成した というヘルパー スクリプトLineageを参照してください。特に を使用していない場合でも、Wiki ページLineageこのディスカッションは継承階層を理解するのに役立つ場合があります。

于 2013-10-28T09:34:26.070 に答える