Стандарт ECMA-262 (JavaScript) в картинках, частина 3


У попередніх частинах розглядалися структури execution context об'єкти Function і вказівник this. У третій частині мова піде про прототипном спадкування.

Як реалізуються класи
В JavaScript немає класів. Там, де в класичному ООП використовуються класи і об'єкти JavaScript застосовуються об'єкти з функціями і об'єкти з даними.



При пошуку властивостей використовується внутрішнє поле [[Prototype]] (воно доступне зовні як __proto__). Якщо властивість не знайдено в об'єкті, то воно шукається у прототипі.
var a = {
n: 1
};

var b = {
__proto__: a,
m: 2
};

console.log(b.n); // виведе 1

Для того, щоб кажды раз при створенні об'єкту не потрібно явно вказувати __proto__ JavaScript можна використовувати функції в якості конструкторів з допомогою оператора new. При інтерпретації ключового слова function щоразу створюється не тільки об'єкт Function, але і пов'язаний з ним об'єкт Prototype.



Якщо викликати функцію
new User()
, а не
User()
, то буде створений новий об'єкт. Властивість __proto__ нового об'єкта буде вказувати на prototype.



При виклику функції через new ThisBinding контексту буде вказувати на створений об'єкт. Якщо в function User написати
this.name = "Unknown"
, то в новому об'єкті з'явиться поле name із вказаним значенням.
"Методи класу" логічно розміщувати в прототипі, в цьому випадку все "об'єкти класу" будуть мати до них доступ.
function User(name) {
this.name = name;
}

User.prototype.getName = function _getName() {
return this.name;
}

var user = new User("John");
console.log(user.getName());

Так як при виклику "методів" використовується звернення через точку:
user.getName()
, то ThisBinding буде вказувати на новий об'єкт
return this.name
повертає значення відповідне значення name.



Важливо розрізняти _proto_ і prototype. Властивість __proto__ ([[Prototype]]) є у всіх об'єктів і використовується для пошуку властивостей. Властивість prototype є тільки у об'єктів Function і використовується при створенні об'єктів через new.

Як реалізується спадкування класів
Спадкування JavaScript реалізується з допомогою ланцюжка прототипів.



Припустимо, від класу User необхідно отнаследовать клас Employee і додати ще один "метод". Для цього потрібно:
  • реалізувати функцію Employee, яка буде використана в якості конструктора,
  • додати у її прототип необхідні функції,
  • вказати __proto__ прототипу Employee посилання на прототип User.
В цьому випадку якщо функція не буде знайдена в одному прототипі пошук буде продовжено у "батьківському прототипі".



Втім, довгі ланцюжки спадкування в JavaScript не вітаються.
Детальніше про прототипних спадкування у стандарті:
Висновок
Читайте стандарт, нічого складного там немає. Головне розібратися в основних поняттях і зв'язках між ними. Рекомендую почати з чогось зрозумілого, наприклад, з виклику функції. Потім – розібратися зі зустрічаються в тексті визначеннями. Рекурсивно повторити.

Також має сенс подивитися на перші релізи стандартів. По-перше, цікаво спостерігати за еволюцією. А по-друге, деякі фічі з'явилися пізніше, тому самі стандарти були простіше. Наприклад, немає поділу на LexicalEnvironment і VariableEnvironment, яке трохи збиває з пантелику.

Якщо хоча б один розробник після прочитання статті розбереться зі стандартом я зможу вважати своє завдання виконаним.

Джерело: Хабрахабр
  • avatar
  • 0

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.