Sobes.tech
Middle

Какво е прототипно наследяване в JavaScript?

sobes.tech AI

Отговор от AI

Обектите в JavaScript наследяват свойства и методи от своите прототипи. Всеки обект има прототип, който е друг обект, чийто свойства и методи са достъпни чрез прототипната верига.

При достъп до свойство на обект, JavaScript първо търси директно в самия обект. Ако не го намери, търсенето продължава в прототипа на този обект, след това в прототипа на прототипа и така нататък, докато свойството бъде намерено или не достигне края на веригата (null).

Прототипното наследяване се различава от класическото наследяване (като в Java или C++), където обектите се създават от класове, които описват тяхната структура и поведение. В JavaScript класовете, появили се в ES6, са синтактичен захар над прототипното наследяване.

Основни аспекти:

  • __proto__: Вътрешно свойство на обекта, сочещо към неговия прототип.
  • prototype: Свойство на конструктора (функция, използвана като конструктор), сочещо към обект, който ще служи като прототип за създаваните екземпляри.
  • Object.getPrototypeOf(obj): Стандартен начин за получаване на прототипа на обекта.
  • Object.setPrototypeOf(obj, proto): Стандартен начин за задаване на прототипа на обекта.

Пример:

// Конструкторска функция
function Animal(name) {
  this.name = name;
}

// Добавяне на метод към прототипа Animal
Animal.prototype.sayHello = function() {
  console.log(`Hello, my name is ${this.name}`);
};

// Създаване на екземпляр
const dog = new Animal("Buddy");

// Викаме метод от прототипа
dog.sayHello(); // Изход: Hello, my name is Buddy

// Прототипът на dog е Animal.prototype
console.log(Object.getPrototypeOf(dog) === Animal.prototype); // Изход: true

// Прототипът на Animal.prototype е Object.prototype
console.log(Object.getPrototypeOf(Animal.prototype) === Object.prototype); // Изход: true

// Краят на веригата на прототипите е null
console.log(Object.getPrototypeOf(Object.prototype) === null); // Изход: true

Сравнение с класическото наследяване (с използване на ES6 класове):

class Animal {
  constructor(name) {
    this.name = name;
  }

  sayHello() {
    console.log(`Hello, my name is ${this.name}`);
  }
}

class Dog extends Animal {
  constructor(name, breed) {
    super(name); // Викаме конструктора на родителския клас
    this.breed = breed;
  }

  bark() {
    console.log("Woof!");
  }
}

const buddy = new Dog("Buddy", "Golden Retriever");
buddy.sayHello(); // Изход: Hello, my name is Buddy (наследява се от Animal)
buddy.bark(); // Изход: Woof! (метод на Dog)

// Класовете в ES6 са захар над прототипите
console.log(Object.getPrototypeOf(Dog) === Animal); // Изход: true (наследяване между класове)
console.log(Object.getPrototypeOf(Dog.prototype) === Animal.prototype); // Изход: true (наследяване на методи чрез прототипи)
console.log(Object.getPrototypeOf(buddy) === Dog.prototype); // Изход: true (екземпляр наследява от прототипа на класа)

Прототипното наследяване е ключова концепция в JavaScript, която е важна за ефективната работа с езика.