2013-10-28 8 views
3

Я изучаю javascript и озадачен. Пример над here который имеет пример, как показано ниже: -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 

Теперь я смущен (<----) в этих двух строках. Когда я говорю Person.call(this);, это просто указывает на Наследование свойств класса Person ... Правильно?

Тогда что это такое?

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

По моим сведениям, .prototype также наследует все свойства?

+0

Я могу показаться очень глупым для людей, которые являются экспертами в javascript. Но будет очень рад, если вы прокомментируете и проголосуете. –

+0

это разные вещи, которые вы должны больше узнать о вызове и применять методы javascript, это будет очень полезно, если вы хотите изучить этот язык программирования – Max

+2

Я тоже не вижу причины для этого. Прототипное наследование сложно понять, и есть много неясной и откровенной неверной информации. –

ответ

3

Чтобы объяснить это, во-первых давайте вспомним, как функции конструктора работают в 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 объект не имеет его собственный свойство называется q, двигатель JavaScript смотрит на g «s прототип, который (опять же) он получил назначен, когда она была создана. Этот прототип имеет свойство q, поэтому двигатель использует его значение.

Напротив, когда мы смотрим на g.a, объект g имеет свое собственное имущество под названием a, поэтому значение используется напрямую.

С этим фундаментом на месте, давайте посмотрим на Student и Parent:

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

Когда мы называем new Student(), внутри вызова Student, this есть (опять же) новый объект, созданный new оператора, имеет Student.prototype в качестве базового прототипа. Но функция Parent не имела возможности что-либо сделать с этим новым объектом. Итак, что делает эта строка, дает Parent шанс сделать то, что ему нужно, сделать для новых объектов, которые он не может сделать с помощью прототипа, например, наша Guide функция, назначая this.a. С технической точки зрения, Parent.call(this); вызывает функцию Parent, гарантируя, что this в вызове Parent это значение, переданное в call (который, в этом случае, this вызова к Student   — например, новый объект). Если вы знакомы с языками на основе классов, это похоже на выполнение super(); (это Java, но вы получаете идею) в производном конструкторе: он дает базовому конструктору возможность инициализировать объект.

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

Поскольку Student предполагается наследовать от Person, то, что код делает это создание прототипа, который будет назначен для объектов, созданных с помощью new Student. Объектом, который он создает, является объект Person.

FWIW, что код не вполне реализует строительную цепь правильно (это чаще, чем это необходимо вызывая Person [как при создании Student.prototypeи когда Student называется], и не в состоянии установить constructor).

Более правильный способ создать Student «S prototype свойства, если мы будем называть 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. Это либо-либо: Либо вызов Parent создать Student.prototype, или вызов Parent в Student, но не то и другое. При построении иерархии с помощью функций-конструкторов обычно требуется вызвать родителя из дочернего конструктора, а не при создании дочернего прототипа. При использовании прямого наследования объектов (без функций конструктора), конечно, вы делаете это по-другому.

Если вы заинтересованы в наследование в JavaScript, я написал вспомогательный скрипт Lineage вы можете захотеть взглянуть на, и, в частности, даже если вы не используете Lineage, this discussion на своей странице вики может быть полезным для понимания иерархий наследования.

+0

@ Crowder: - Всего 3 слова для вас. Вы удивительны ... Большое спасибо, много и lottt ... –

+0

@Idothisallday: LOL Вы рады. Я понял, что не стал рассказывать о том, что этот код делает неправильно, поэтому я передумал, что после того, как вы приняли ответ. Если вы перечитаете, начиная с «FWIW» примерно на две трети пути вниз, именно там я его исправил. Лучший, –

Смежные вопросы