2017-02-06 2 views
-1

У меня есть вопрос относительно классического наследования против прототипического наследования. Я хотел посмотреть, что лучше?Usecase for Classical vs Prototypical

Предположим, у нас есть функция, называемая familyTree.

function familyTree(){ 
    this.lastname = "xyz"; 
} 

Если я хочу, чтобы добавить какие-либо дополнительные детали для них, насколько я читал, мы можем наследовать родительский двумя способами:

1: прототипичный путь:

familyTree.prototype.personDetails = function(){ 

this.firstName = "abc"; 
this.middleName = "middle1"; 

var newToString = function(name){ //overwriting toString method 
    console.log("The name is: "+name+"Middle Name is "+middleName); 
} 
} 

2: Классическая way with 'new' keyword

var newPerson = new familyTree(); 
    newPerson.firstName = "abc"; 
    newPerson.middleName = "middle1"; 
    newperson.newToString = function (name){ 
    console.log("The name is: "+name+"Middle Name is "+middleName); 
    } 

Скажем, если я хочу создать 100 разных средних имен.

Что имеет смысл? Использование классического наследства или прототипа? Потому что использование Classical может копировать все объекты, но с использованием прототипа может получить все беспорядочное.

Просьба проиллюстрировать, когда нужно использовать классический прототип.

+0

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

+0

И второй пример устанавливает свойство «firstName» дважды. –

+0

Свойства должны быть определены в конструкторе, чтобы каждый новый экземпляр мог хранить значения, которые не зависят от какого-либо другого экземпляра («специфичный для экземпляра»). Методы должны быть добавлены к прототипу конструктора, чтобы функция не должна храниться как часть каждого экземпляра, но все экземпляры все равно наследуют поведение. Поведение не меняется от экземпляра к экземпляру, но данные делают. –

ответ

2

Существует только один вид наследования в JavaScript и это прототипическое наследование. «Классическое» наследование не существует в JavaScript.

Несмотря на «синтаксический сахар», что язык JavaScript должен сделать разработчиками ООП, которые очень удобны с программированием на основе классов, дома (включая ключевое слово class), на самом деле JavaScript не имеет или не использует классы. Этот языковой словарь просто предназначен для того, чтобы вы чувствовали себя все тепло и нечетко.

Ваш вопрос не спрашивает о наследовании, он спрашивает, следует ли привязывать свойства к функции-конструктору или прототипу.

Смотрите комментарии кода для объяснения:

// When you create a function that you will use to create object instances, 
 
// you have a "constructor function". By convention, these functions should 
 
// be named in PascalCase as a way to let others know that they are to be 
 
// used in conjunction with the "new" keyword as a constructor. 
 
function FamilyTree(first, middle, last){ 
 
    
 
    // Because this function will be used to create instances of a 
 
    // FamilyTree object, each instance created will need to store 
 
    // data that is different from another. This is done with "instance 
 
    // properties" and they are created by prepending the property name 
 
    // with "this.". The "this" object will be referenced by the object 
 
    // instance variable that is used when the instance is created: 
 
    this.firstName = first; 
 
    this.middleName = middle; 
 
    this.lastName = last; 
 
    
 
} 
 

 
// JavaScript objects don't technically have "methods" - - they 
 
// have properties that store functions and functions are how 
 
// to add behavior to an object. Since the behaviors of an object 
 
// don't typically change from instance to instance, you should not 
 
// add them to the constructor function. If you did, the code would 
 
// work, but each instance would need to store a copy of the exact 
 
// same behavior, making the objects unnecessarialy large in memory. 
 
// Instead, we attach behaviors that all instances of an object will 
 
// need to the prototype of the constructor and that way all instances 
 
// created from the constructor will inherit the behaviors, but the 
 
// acutal behavior will only be stored once, thus saving on memory space 
 
// and eliminating the possibility of one instance behaving differently 
 
// than others, unintentionally. 
 

 
// Implementing "methods" that all FamilyTree instances will inherit: 
 
FamilyTree.prototype.newToString = function(name){ 
 
    return "First name: " + this.firstName + ", Last Name: " + this.lastName; 
 
} 
 

 
// The constructor function's prototype (as with all objects) derives from "Object" 
 
// which defines a "toString" property, by re-defining that property on the constructor's 
 
// prorotype, we will be able to override the inherited one 
 
FamilyTree.prototype.toString = function(name){ 
 
    return this.lastName + ", " + this.firstName; 
 
} 
 
    
 
// To use this object, we have a few choices, but the simplest one is to just instantiate it: 
 
var myFamilyTree = new FamilyTree("John","Fitzgerald","Kennedy"); 
 

 
// Now, we just work with the instance: 
 
console.log(myFamilyTree.firstName); 
 
console.log(myFamilyTree.middleName); 
 
console.log(myFamilyTree.lastName); 
 
console.log(myFamilyTree.newToString()); 
 
console.log(myFamilyTree.toString());

Теперь, приведенный выше код работает, но технически не организована хорошо, так как объект является «Family Tree», и все это на самом деле магазины - это имя одного человека и некоторые способы вывода этого имени. Не много родословной. На самом деле это «семейное дерево» должно быть составлено из других объектов (например, многие индивидуальные люди должны быть включены вместе с другими соответствующими данными семейного древа). Если мы применим ООП "Single Responsibility Principle" («У класса/модуля должна быть только одна причина для изменения»), нам нужно, чтобы объект Family Tree имел меньшие части объекта. Все это будет включать делаем исходный объект имеет свойство, которое хранит массив людей объекты:

// First, make objects that represent the parts of the whole 
 
function Person(first, middle, last, dob, maiden){ 
 
    // Instance properties are added to the constructor, which makes individual instances: 
 
    this.firstName = first; 
 
    this.middleName = middle; 
 
    this.lastName = last; 
 
    this.dob = dob; 
 
    this.maidenName = maiden; 
 
} 
 

 
// Behavior properties are added to the constructor's prototype to avoid duplication 
 
// of code across instances: 
 
Person.prototype.newToString = function(name){ 
 
    return "First name: " + this.firstName + ", Last Name: " + this.lastName; 
 
} 
 

 
Person.prototype.toString = function(name){ 
 
    return this.lastName + ", " + this.firstName; 
 
} 
 

 
// Then create an object that becomes the sum of the parts: 
 
function FamilyTree(){ 
 
    // We just need a way to store family members. 
 
    // Each FamilyTree instance can have different members, so an instance property 
 
    // is needed: 
 
    this.people = []; 
 
} 
 

 
// And, again, behaviors are added to the prototype: 
 
FamilyTree.prototype.getMemberCount = function(){ 
 
    return this.people.length; 
 
} 
 

 
FamilyTree.prototype.addMember = function(personObject){ 
 
    this.people.push(personObject); 
 
} 
 

 
FamilyTree.prototype.removeMember = function(personObject){ 
 
    var index = this.people.findIndex(function(element){ 
 
    return personObject === element; 
 
    }); 
 
    this.people.splice(index, 1); 
 
} 
 

 
// And, because the tree stores an array, we can looop through it: 
 
FamilyTree.prototype.enumerate = function(){ 
 
    var result = ""; 
 
    this.people.forEach(function(person){ 
 
    result += person.firstName + " " + person.middleName + " " + person.lastName + 
 
      " (" + person.newToString() + " [" + person.toString() + "])"; 
 
    }); 
 
    return result; 
 
}; 
 

 
    
 
// Now, to use the Family Tree, we first need some people 
 
var jack = new Person("John","Fitzgerald","Kennedy", new Date(1917, 4, 29)); 
 
var bobby = new Person("Robert", "Francis", "Kennedy", new Date(1925, 11, 20)); 
 
var teddy = new Person("Edward","Moore","Kennedy", new Date(1932, 1, 22)); 
 

 
// Now, we add those objects to a new Family Tree instance: 
 
var kennedyTree = new FamilyTree(); 
 
kennedyTree.addMember(jack); 
 
kennedyTree.addMember(bobby); 
 
kennedyTree.addMember(teddy); 
 
console.log("The tree contains: " + kennedyTree.getMemberCount() + " members."); 
 
console.log(kennedyTree.enumerate()); 
 

 
// Let's remove a member: 
 
kennedyTree.removeMember(bobby); 
 
console.log("The tree contains: " + kennedyTree.getMemberCount() + " members."); 
 
console.log(kennedyTree.enumerate());

+0

Итак, вы говорите мне, что я читал в: http://stackoverflow.com/questions/19633762/classical-inheritance-vs-protoypal-inheritance-in-javascript - это просто синтаксический сахар (/ gimmic) над прототипическим наследованием? и другая статья неверна? Потому что в решении автор говорит, что наследование разделено на прототипное и классическое (поэтому я смущен) – TechnoCorner

+0

@TechnoCorner Да. На самом деле, если вы читаете ответ на сообщение, которое вы ссылаетесь, он говорит: «Оба образца кода, которые вы продемонстрировали в своем вопросе, используют прототипное наследование. Фактически любой объектно-ориентированный код, который вы пишете на JavaScript, является парадигмой прототипа наследование. JavaScript просто не имеет классического наследования ». * –

+0

@TechnoCorner Что вы читаете о типах наследования вообще. Но из того, что я видел в этом посте и в этих статьях, они правильно указывают, что JavaScript не имеет классического наследования. Поймите, что только потому, что язык Object-Oriented не означает, что он должен реализовать определенный тип наследования - только для того, чтобы он поддерживал какое-то наследование. –

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