Classes Emit
What's up with the IIFE
Що відбувається з IIFE. js код, згенерований для класу, міг бути таким:
Причина, по якій він загорнутий у функцію, що негайно викликається (Immediately-Invoked Function Expression - IIFE)
має відношення до спадщини. Це дозволяє TypeScript роботать з базовим класом як со змінною _super
.
Зверніть увагу, що IIFE дозволяє TypeScript легко фіксувати базовий клас Point
у змінній _super
яка постійно використовується в тілі класу.
__extends
__extends
Розширення Ви помітите, що як тільки ви успадкуєте клас, TypeScript також генерує таку функцію:
Тут d
відноситься до похідного класу, а b
відноситься до базового класу. Ця функція робить дві речі:
копіює статичні члени базового класу в дочірній клас, тобто
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
встановлює прототип дочірнього класу як посилання на батьківське
proto
тобто фактичноd.prototype.__proto__ = b.prototype
Люди рідко мають проблеми з розумінням 1 пункту, але багатьом людям важко зрозуміти пункт 2. Тож пояснення є доречним.
d.prototype.__proto__ = b.prototype
Після того як я навчав багатьох людей цьому, я вважаю наступне пояснення найпростішим. Спочатку ми пояснимо, як код із __extends еквівалентний простому d.prototype.proto = b.prototype , а потім пояснимо, чому цей рядок сам по собі важливий. Щоб все це зрозуміти, потрібно знати такі речі:
__proto__
prototype
вплив
new
наthis
всередині викликаної функціївплив
new
наprototype
та__proto__
Усі об’єкти в JavaScript містять __proto__
. Цей елемент часто недоступний у старих браузерах (іноді в документації ця магічна властивість згадується як [[prototype]]
). Він має одну мету: якщо властивість не знайдено в об’єкті під час пошуку (наприклад, obj.property
), тоді вона шукається за obj.__proto__.property
. Якщо його все ще не знайдено, тоді obj.__proto__.__proto__.property
доки: його не буде знайдено , або останній .__proto__
сам по собі буде нульовим . Це пояснює, чому кажуть, що JavaScript підтримує успадкування прототипів із коробки. Це показано в наступному прикладі, який можна запустити в консолі Chrome або Node.js:
Круто, що ви зрозуміли __proto__
. Іншим корисним фактом є те, що всі function
в JavaScript мають властивість під назвою prototype
і що вони мають constructor
- член , що вказує на функцію. Це показано нижче:
Тепер давайте розглянемо вплив new
на this
всередині викликаної функції . По суті, this
всередині викликаної функції вказуватиме на щойно створений об’єкт, який буде повернено функцією. Легко побачити, якщо ви змінюєте властивість this
всередині функції:
Єдине, що вам потрібно знати, це те, що виклик new
для функції призначає prototype
функції __proto__
новоствореного об’єкта, який повертається викликом функції. Ось код, який ви можете запустити щоб повністю зрозуміти це:
Тепер подивіться на наступне прямо з __extends
. Я взяв на себе сміливість пронумерувати ці рядки:
Читання цієї функції у зворотному порядку d.prototype = new __()
у рядку 3 фактично означає d.prototype = {__proto__ : __.prototype}
(через вплив new на prototype
та __proto__
), поєднуючи його з попереднім рядком ( тобто рядок 2 __.prototype = b.prototype;
) ви отримаєте d.prototype = {__proto__ : b.prototype}
. Але зачекайте, ми хотіли d.prototype.__proto__
, тобто лише прото змінили та зберегли старий d.prototype.constructor
. Ось де значення першого рядка (тобто function __() { this.constructor = d; }
) з’являється. Тут ми фактично матимемо d.prototype = {__proto__ : __.prototype, constructor : d}
(оскільки вплив new
на this
всередині викликаної функції). Отже, оскільки ми відновлюємо d.prototype.constructor
, єдине, що ми дійсно змінили, це __proto__
, отже, d.prototype.__proto__ = b.prototype
.
d.prototype.__proto__ = b.prototype
significance
Значення d.prototype.__proto__ = b.prototype
Важливість полягає в тому, що він дозволяє вам додавати функції-члени до дочірнього класу та успадковувати інші від базового класу. Це демонструє такий простий приклад:
Загалом bird.fly
шукатиметься з bird.__proto__.fly
(пам’ятайте, що new
робить bird.__proto__
вказівним на Bird.prototype
), а bird.walk
(успадкований член) шукатиметься з bird.__proto__.__proto__.walk
(як bird.__proto__ == Bird.prototype
і bird.__proto__.__proto__
== Animal.prototype
).
Last updated