Що таке ланцюг прототипів (prototype chain) в javascript?

Прототип

Я вирішив поговорити про це, оскільки вважаю, що це одна з найбільш заплутаних тем в JS. У середньому, під час кожного інтерв'ю, принаймні одне запитання обов'язково стосується цієї теми.

Прототип

Примітка: "Прототип" - це спеціальне властивість, доступна лише для об'єктів-функцій.

Ця властивість автоматично надається функціям при їх запуску.

Майже кожен об'єкт пов'язаний з іншим об'єктом. Ця зв'язок встановлюється за допомогою прототипу. Об'єкти успадковують методи та властивості батьківського об'єкта через прототип.

Властивість prototype є в самій функції (Animal), а не в її екземплярах (Dog).

Щоб краще зрозуміти, давайте спробуємо розібрати наступний приклад крок за кроком:

Спершу подивимося, що відбувається при виконанні першого рядка:

Коли функція виконується, до Animal (ознаки того, що вона оголошена з ключовим словом function) автоматично додається властивість.

Що стається, коли створюється об'єкт Dog?

  1. Тригерується Animal.prototype.constructor і створюється новий об'єкт.
  2. Новий об'єкт призначається змінній Dog. (Dog = {})
  3. Створюється властивість Dog, яка вказує на __proto__ батьківського прототипу. (Dog.__proto__ === Animal.prototype)

Додатково, давайте додамо до Animal властивістьcolor

Оскільки у Dog немає властивості кольору, то властивість Dog.__proto__ буде шукати її та поверне після знаходження.

Прототип: proto проти [[Prototype]]

Що таке[[Prototype]]? (Приватне)

Це приватний об'єкт, який використовується JavaScript на задньому плані ( недоступний розробнику ), що показує прототип об'єкту.

Що таке__proto__? (Публічне)

Це внутрішній властивість, яка обов'язково присутня в кожному об'єкті.

[[Prototype]]Оскільки ми не можемо звертатися до нього напряму, для цього ми користуємося властивістю

__proto__може бути або Object, або Null.

Як ми можемо створити об'єкт без прототипу?

Загалом, кожен об'єкт в JS успадковує Object, а Object.prototype завжди є Null.

Object.create(null)

ПРИМІТКА: Пряме встановлення proto вже не рекомендується JavaScript. (Doberman.proto = Dog)

УСТАРІЛЕ. Це наведено лише для прикладу. НЕ РОБІТЬ ТАК у реальному коді. //джерело: Mozilla

Pрототипна Ланцюг

Усі об'єкти в JS є екземплярами Object .

Кожен об'єкт може успадковувати лише один об'єкт одночасно.

Об'єкти

Як шукати будь-яке поле об'єкта?

  1. Спочатку поле object шукається у ньому самому, якщо знайдено, воно повертається,

якщо не знайдено, шукається також object.__proto__.

Якщо його ще не знайдено, воно шукається в object.__proto__.__proto__

Процес продовжується в такому порядку (object.__proto__.__proto__.__proto__) до досягнення Глобального Об'єкту

  1. Якщо в кінці не можна знайти результат, повертається undefined.

У прикладі нижче, успадковані поля (code, name) не знаходяться всередині District, тому вони повертаються зсередини District.__proto__.

Масиви та функції

Давайте розглянемо, що успадковується при створенні масиву:

  1. Перший успадковує властивості від Array.prototype, тому має методи, такі як forEach, join.
  2. Потім успадковує властивості від Object.prototype, тому об'єкт має методи, такі як toString, keys.

Щодо функцій:

  1. Перша успадковує властивості від Function.prototype, тому має методи, такі як call, bind.
  2. Потім успадковує властивості від Object.prototype, тому об'єкт має методи, такі як toString, keys.

З допомогою Object.create()

Метод Object.create() дозволяє створити новий об'єкт з використанням існуючого, створюючи ланцюг прототипів.

Значення null означає відсутність прототипу.

У випадку видалення b.id з b, id залишається в a, оскільки id є в b.__proto__.

Якщо було б видалено a.id, це призвело б до видалення з обох.

Методи-доступу та задавачі

Як бачимо з прикладу, методи setColor та getColor належать об'єкту Dog. Оскільки ми успадкували Doberman від Dog, ці методи вже існують в Dog.

Зверніть увагу, що методи setColor та getColor змінюють лише властивість об'єкта, з якими вони взаємодіють.

Ітерація

Для перебору властивостей успадкованого об'єкта також використовується цикл For in.

Для кожного класу наслідника, такого як Dog та Cat, також буде доступна властивість color, оскільки всі об'єкти успадковують тип Object.

Глобальний об'єкт як функція

Глобальний об’єкт може бути викликаний як функція, що означає, що глобальний об’єкт фактично є функцією. Тому він має властивість prototype.

Усі об'єкти успадковують тип Object, у тому числі Dog та Cat.

Це означає, що Dog.proto та Cat.proto також мають властивість color.

pic

Оператор "instanceof"

Припустимо, у нас є об'єкт dog і ми хочемо перевірити, чи належить він класу Dog. Ми можемо використовувати оператор instanceof наступним чином:

pic

Завершивши розгляд методів, можна подивитися на процес з діаграмою:

Для більш чіткого уявлення, можна переглянути діаграму за посиланням:

pic

pic

[Посилання на діаграму:](https://viewer.diagrams.net/?tags=%7B%7D&highlight=0000ff&edit=_blank&layers=1&nav=1&title=Untitled+Diagram.

На чому зображені дві діаграми зображуючі структуру даних мережі, і синтаксичну модель, співвідношення між даними та сервером (Server-Data Relationship), і інші концепції. Обидві діаграми можна переглянути за посиланням вище.

Перекладено з: proto, prototype, [[Prototype]], Prototype Chain

Примітки:

Що таке ланцюг прототипів (prototype chain) в javascript?

Ланцюг прототипів (prototype chain) в JavaScript - це механізм, за допомогою якого об'єкти в JavaScript успадковують властивості та методи від інших об'єктів. Кожен об'єкт має внутрішню властивість [[Prototype]], яка є посиланням на інший об'єкт. Коли спроба отримати доступ до властивості, яка не існує в поточному об'єкті, JavaScript автоматично шукає цю властивість в об'єкті [[Prototype]]. Цей процес продовжується до тих пір, поки JavaScript не знайде властивість або не досягне кінця ланцюга прототипів (як правило, це об'єкт Object.prototype), після чого повертає undefined. Ось простий приклад ланцюга прототипів в JavaScript:

function Person(name) {
    this.name = name;
}

Person.prototype.sayHello = function() {
    return "Hello, I'm " + this.name;
}

function Employee(name, job) {
    Person.call(this, name);
    this.job = job;
}

Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;

Employee.prototype.sayHello = function() {
    return Person.prototype.sayHello.call(this) + ", and I'm a " + this.job;
}

var employee = new Employee("John", "developer");

console.log(employee.sayHello()); // "Hello, I'm John, and I'm a developer"

У цьому прикладі, Employee успадковує властивості та методи від Person через ланцюг прототипів. Коли викликається метод sayHello на об'єкті employee, JavaScript спочатку шукає цей метод в об'єкті employee. Не знайшовши його там, він переходить до прототипу employee, який є об'єктом Employee.prototype, і знаходить метод там.

Що таке прототип об'єкта JS?

Прототип об'єкта в JavaScript - це об'єкт, який використовується для успадкування властивостей та методів іншими об'єктами. Кожен об'єкт в JavaScript має внутрішню властивість [[Prototype]], яка є посиланням на інший об'єкт. Цей інший об'єкт називається прототипом об'єкта. Коли спроба отримати доступ до властивості, яка не існує в поточному об'єкті, JavaScript автоматично шукає цю властивість в прототипі об'єкта. Цей процес продовжується до тих пір, поки JavaScript не знайде властивість або не досягне кінця ланцюга прототипів (як правило, це об'єкт Object.prototype), після чого повертає undefined. Ось простий приклад прототипу об'єкта в JavaScript:

function Person(name) {
    this.name = name;
}

Person.prototype.sayHello = function() {
    return "Hello, I'm " + this.name;
}

var person = new Person("John");

console.log(person.sayHello()); // "Hello, I'm John"

У цьому прикладі, Person.prototype є прототипом об'єкта Person, і він успадковується об'єктом person. Коли викликається метод sayHello на об'єкті person, JavaScript спочатку шукає цей метод в об'єкті person. Якщо він не знайдений, він шукає його в прототипі об'єкта Person, і викликає його, якщо він знайдений.

Що таке конструктор JS?

Конструктор в JavaScript - це функція, яка використовується для створення нових об'єктів. Конструктори в JavaScript використовуються для створення нових об'єктів з однаковою структурою та методами. Конструктори в JavaScript можуть бути викликані за допомогою ключового слова new, яке створює новий об'єкт на основі конструктора. Ось приклад конструктора в JavaScript:

function Person(name) {
    this.name = name;
}

Person.prototype.sayHello = function() {
    return "Hello, I'm " + this.name;
}

var person = new Person("John");

console.log(person.sayHello()); // "Hello, I'm John"

У цьому прикладі, Person є конструктором, який створює нові об'єкти з властивістю name та методом sayHello. Коли викликається конструктор Person за допомогою ключового слова new, створюється новий об'єкт person з властивістю name та методом sayHello.

Prototype в JS

Прототип в JavaScript - це об'єкт, який використовується для успадкування властивостей та методів іншими об'єктами. Кожен об'єкт в JavaScript має внутрішню властивість [[Prototype]], яка є посиланням на інший об'єкт. Цей інший об'єкт називається прототипом об'єкта. Коли спроба отримати доступ до властивості, яка не існує в поточному об'єкті, JavaScript автоматично шукає цю властивість в прототипі об'єкта. Цей процес продовжується до тих пір, поки JavaScript не знайде властивість або не досягне кінця ланцюга прототипів (як правило, це об'єкт Object.prototype), після чого повертає undefined. Ось простий приклад прототипу об'єкта в JavaScript:

function Person(name) {
    this.name = name;
}

Person.prototype.sayHello = function() {
    return "Hello, I'm " + this.name;
}

var person = new Person("John");

console.log(person.sayHello()); // "Hello, I'm John"

У цьому прикладі, Person.prototype є прототипом об'єкта Person, і він успадковується об'єктом person. Коли викликається метод sayHello на об'єкті person, JavaScript спочатку шукає цей метод в об'єкті person. Якщо він не знайдений, він шукає його в прототипі об'єкта Person, і викликає його, якщо він знайдений.

String prototype в js

String.prototype в JavaScript - це об'єкт, який містить методи для роботи з рядками. Кожен рядок в JavaScript є об'єктом типу String, який успадковує методи з String.prototype. String.prototype містить методи для роботи з рядками, такі як charAt, charCodeAt, concat, indexOf, lastIndexOf, match, replace, search, slice, split, substr, substring, toLowerCase, toUpperCase, trim та багато інших. Ось приклад використання методів String.prototype в JavaScript:

var str = "Hello, World!";

console.log(str.charAt(0)); // "H"
console.log(str.indexOf("World")); // 7
console.log(str.toUpperCase()); // "HELLO, WORLD!"

У цьому прикладі, str є рядком, який успадковує методи з String.prototype. Коли викликаються методи charAt, indexOf та toUpperCase на рядку str, JavaScript використовує методи з String.prototype для виконання відповідних операцій.

Наслідування в JS

Наслідування в JavaScript - це механізм, за допомогою якого об'єкти успадковують властивості та методи від інших об'єктів. Кожен об'єкт в JavaScript має внутрішню властивість [[Prototype]], яка є посиланням на інший об'єкт. Коли спроба отримати доступ до властивості, яка не існує в поточному об'єкті, JavaScript автоматично шукає цю властивість в прототипі об'єкта. Цей процес продовжується до тих пір, поки JavaScript не знайде властивість або не досягне кінця ланцюга прототипів (як правило, це об'єкт Object.prototype), після чого повертає undefined. Ось простий приклад наслідування в JavaScript:

function Person(name) {
    this.name = name;
}

Person.prototype.sayHello = function() {
    return "Hello, I'm " + this.name;
}

function Employee(name, job) {
    Person.call(this, name);
    this.job = job;
}

Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;

Employee.prototype.sayHello = function() {
    return Person.prototype.sayHello.call(this) + ", and I'm a " + this.job;
}

var employee = new Employee("John", "developer");

console.log(employee.sayHello()); // "Hello, I'm John, and I'm a developer"

У цьому прикладі, Employee успадковує властивості та методи від Person через ланцюг прототипів. Коли викликається метод sayHello на об'єкті employee, JavaScript спочатку шукає цей метод в об'єкті employee. Не знайшовши його там, він переходить до прототипу employee, який є об'єктом Employee.prototype, і знаходить метод там.

Що таке this в JS

Ключове слово this в JavaScript вказує на поточний об'єкт, в якому викликається функція. Значення this залежить від контексту виклику функції. Якщо функція викликається як метод об'єкта, this вказує на цей об'єкт. Якщо функція викликається як функція, this вказує на глобальний об'єкт (наприклад, window в браузері). Якщо функція викликається за допомогою call, apply або bind, this вказує на об'єкт, який передається як перший аргумент цих методів. Ось приклади використання this в JavaScript:

var person = {
    name: "John",
    sayHello: function() {
        return "Hello, I'm " + this.name;
    }
};

console.log(person.sayHello()); // "Hello, I'm John"

function greet() {
    return "Hello, I'm " + this.name;
}

var person = {
    name: "John"
};

console.log(greet.call(person)); // "Hello, I'm John"

У першому прикладі, this вказує на об'єкт person, оскільки метод sayHello викликається як метод об'єкта. У другому прикладі, this вказує на об'єкт, який передається методом call, тобто об'єкт person.

Прототипне успадкування в js

Прототипне наслідування в JavaScript - це механізм, за допомогою якого об'єкти успадковують властивості та методи від інших об'єктів. Кожен об'єкт в JavaScript має внутрішню властивість [[Prototype]], яка є посиланням на інший об'єкт. Коли спроба отримати доступ до властивості, яка не існує в поточному об'єкті, JavaScript автоматично шукає цю властивість в прототипі об'єкта. Цей процес продовжується до тих пір, поки JavaScript не знайде властивість або не досягне кінця ланцюга прототипів (як правило, це об'єкт Object.prototype), після чого повертає undefined. Ось простий приклад прототипного наслідування в JavaScript:

function Person(name) {
    this.name = name;
}

Person.prototype.sayHello = function() {
    return "Hello, I'm " + this.name;
}

function Employee(name, job) {
    Person.call(this, name);
    this.job = job;
}

Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;

Employee.prototype.sayHello = function() {
    return Person.prototype.sayHello.call(this) + ", and I'm a " + this.job;
}

var employee = new Employee("John", "developer");

console.log(employee.sayHello()); // "Hello, I'm John, and I'm a developer"

У цьому прикладі, Employee успадковує властивості та методи від Person через ланцюг прототипів. Коли викликається метод sayHello на об'єкті employee, JavaScript спочатку шукає цей метод в об'єкті employee. Не знайшовши його там, він переходить до прототипу employee, який є об'єктом Employee.prototype, і знаходить метод там.

Типи даних в js

В JavaScript є кілька типів даних, включаючи примітивні типи даних та об'єктові типи даних. Примітивні типи даних включають number, string, boolean, null, undefined, symbol та bigint. Об'єктові типи даних включають object, function, array, date, regexp та інші. Ось приклади використання різних типів даних в JavaScript:

var number = 42;
var string = "Hello, World!";
var boolean = true;
var nullValue = null;
var undefinedValue = undefined;
var symbolValue = Symbol("foo");
var bigintValue = 9007199254740991n;

var object = {
    key: "value"
};

function func() {
    return "Hello, World!";
}

var array = [1, 2, 3];
var date = new Date();
var regexp = /hello/g;

У цьому прикладі, number, string, boolean, null, undefined, symbol та bigint є примітивними типами даних, а object, function, array, date та regexp є об'єктовими типами даних.

Замикання в JS

Замикання в JavaScript - це механізм, за допомогою якого функція зберігає доступ до змінних з області видимості, в якій вона була створена. Замикання в JavaScript дозволяють створювати функції, які зберігають доступ до змінних, навіть після того, як вони вийшли з області видимості. Ось приклад використання замикань в JavaScript:

function createCounter() {
    var count = 0;
    return function() {
        count++;
        return count;
    };
}

var counter = createCounter();

console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

У цьому прикладі, функція createCounter створює замикання, яке зберігає доступ до змінної count. Кожного разу, коли викликається функція counter, вона збільшує значення count на одиницю та повертає його.

Leave a Reply

Your email address will not be published. Required fields are marked *