de Pranav Jindal

Prototip în JavaScript: este ciudat, dar iată cum funcționează

Prototip in JavaScript este ciudat dar iata cum functioneaza

Următoarele patru linii sunt suficiente pentru a deruta majoritatea dezvoltatorilor JavaScript:

Object instanceof Function//true
Object instanceof Object//true
Function instanceof Object//true
Function instanceof Function//true

Prototipul în JavaScript este unul dintre cele mai uimitoare concepte, dar nu îl puteți evita. Indiferent cât de mult îl ignorați, veți întâlni puzzle-ul prototip în timpul vieții dvs. JavaScript.

Să recunoaștem deci.

Începând cu elementele de bază, există următoarele tipuri de date în JavaScript:

  1. nedefinit
  2. nul
  3. număr
  4. şir
  5. boolean
  6. obiect

Primele cinci sunt tipuri de date primitive. Acestea stochează o valoare de tipul lor, cum ar fi un boolean și pot fi adevărate sau false.

Ultimul „obiect” este un tip de referință pe care îl putem descrie ca o colecție de perechi cheie-valoare (dar este mult mai mult).

În JavaScript, obiecte noi sunt create folosind Constructor de obiecte funcţie (sau obiect literal {}) care oferă metode generice precum toString() și valueOf().

Funcțiile din JavaScript sunt obiecte speciale care pot fi „numit ”. Le realizăm și folosind Funcția constructor de funcții (sau funcțional literal). Faptul că acestea constructori sunt obiecte, precum și funcția m-a încurcat întotdeauna, în același mod în care ghicitoarea cu ouă de pui îi încurcă pe toți.

Înainte de a începe cu prototipuri, vreau să clarific că există două prototipuri în JavaScript:

  1. prototip: Acesta este un obiect special care este atribuit ca proprietate a oricărei funcții pe care o realizați în JavaScript. Permiteți-mi să fiu clar aici, este deja prezent pentru orice funcție pe care o faceți, dar nu este obligatorie pentru funcțiile interne furnizate de JavaScript (și funcția returnată de bind). Acest prototype este același obiect la care este indicat [[Prototype]](vezi mai jos) a obiectului nou creat din acea funcție (folosind new cuvânt cheie).
  2. [[Prototype]]: Aceasta este o proprietate ascunsă cumva pe fiecare obiect care este accesat de contextul de rulare dacă o anumită proprietate care este citită pe obiect nu este disponibilă. Această proprietate este pur și simplu o referință la prototype a funcției din care a fost făcut obiectul. Poate fi accesat în script folosind special getter-setter (subiect pentru altă zi) numit __proto__. Există alte modalități noi de a accesa acest prototip, dar, din motive de scurtă durată, mă voi referi la [[Prototype]] folosind __proto__.
var obj = {}var obj1 = new Object()

Cele două afirmații de mai sus sunt afirmații egale atunci când sunt utilizate pentru a crea un obiect nou, dar multe se întâmplă atunci când executăm oricare dintre aceste afirmații.

Când fac un obiect nou, acesta este gol. De fapt nu este gol deoarece este o instanță a Object constructor și obține în mod inerent o referință de prototype de Object, care este indicat de __proto__ a obiectului nou creat.

Prototip in JavaScript este ciudat dar iata cum functioneaza

Dacă ne uităm la prototype de Object funcția constructor, arată la fel ca __proto__ de obj. De fapt, acestea sunt două indicații care se referă la același obiect.

1612044187 9 Prototip in JavaScript este ciudat dar iata cum functioneaza
obj.__proto__ === Object.prototype//true

Fiecare prototype a unei funcții are o proprietate inerentă numită constructor care este un indicator către funcția în sine. În cazul în care Object funcţie, prototype are constructor care arată înapoi la Object.

Object.prototype.constructor === Object//true
1612044187 783 Prototip in JavaScript este ciudat dar iata cum functioneaza

În imaginea de mai sus, partea stângă este imaginea extinsă a Objectconstructor. Trebuie să vă întrebați care sunt toate celelalte funcții ale acestuia. Ei bine, funcțiile sunt obiecte, astfel încât să poată avea proprietăți asupra lor ca și alte obiecte.

Dacă vă uitați atent, Object (pe stânga) în sine are o __proto__ ceea ce înseamnă că Object trebuie să fi fost realizat dintr-un alt constructor care are un prototype. La fel de Object este un obiect funcțional, trebuie să fi fost realizat folosind Function constructor.

1612044187 476 Prototip in JavaScript este ciudat dar iata cum functioneaza

__proto__ de Object arată la fel ca prototype de Function.Când verific egalitatea ambelor, ele se dovedesc a fi aceleași obiecte.

Object.__proto__ === Function.prototype//true

Dacă vă uitați atent, veți vedea Function în sine are o __proto__ ceea ce înseamnă că Function funcția constructor trebuie să fi fost făcută dintr-o funcție constructor care are o prototype. La fel de Function în sine este un funcţie, trebuie să fi fost realizat folosind Function constructor, adică el însuși. Știu că sună ciudat, dar când îl verifici, se dovedește a fi adevărat.

1612044188 306 Prototip in JavaScript este ciudat dar iata cum functioneaza

__proto__ de Function și prototype de Function sunt de fapt două indicii referitoare la același obiect.

Function.prototype === Function.__proto__\true

După cum sa menționat anterior, constructor din oricare prototype ar trebui să indice spre funcția care deține asta prototype. constructor de prototype de Function arată înapoi la Function în sine.

Function.prototype.constructor === Function\true
1612044188 875 Prototip in JavaScript este ciudat dar iata cum functioneaza

Din nou, prototype de Function are o __proto__ Ei bine, nu este o surpriză … prototype este un obiect, poate avea unul. Dar observați, de asemenea, că indică prototype de Object.

Function.prototype.__proto__ == Object.prototype\true

Deci, putem avea o hartă principală aici:

1612044188 329 Prototip in JavaScript este ciudat dar iata cum functioneaza
instanceof Operatora instanceof b

instanceof operatorul caută obiectul b arătat de oricare dintre constructor(s) de înlănțuit __proto__ pe a. Citește asta din nou! Dacă găsește o astfel de referință, se întoarce true altceva false.

Acum revenim la primele noastre patru instanceof declarații. Am scris declarații corespunzătoare care fac instanceof întoarcere true pentru următoarele:

Object instanceof FunctionObject.__proto__.constructor === Function
Object instanceof ObjectObject.__proto__.__proto__.constructor === Object
Function instanceof FunctionFunction.__proto__.constructor === Function
Function instanceof ObjectFunction.__proto__.__proto__.constructor === Object

Phew !! Chiar și spaghetele sunt mai puțin încurcate, dar sper că lucrurile sunt mai clare acum.

Aici am ceva ce nu am subliniat mai devreme că prototype de Object nu are __proto__.

De fapt are un __proto__ dar asta este egal cu null. Lanțul trebuia să se termine undeva și se termină aici.

Object.prototype.__proto__\null

Al nostru Object, Function, Object.prototypeși Function.prototype au, de asemenea, proprietăți care sunt funcții, cum ar fi Object.assign, Object.prototype.hasOwnPropertyși Function.prototype.call. Acestea sunt funcții interne care nu au prototype și sunt, de asemenea, cazuri de Function și au o __proto__ care este un indicator către Function.prototype.

1612044188 11 Prototip in JavaScript este ciudat dar iata cum functioneaza
Object.create.__proto__ === Function.prototype\true

Puteți explora alte funcții de constructor cum ar fi Arrayși Date, sau luați obiectele lor și căutați prototype și __proto__. Sunt sigur că vei putea distinge modul în care totul este conectat.

Interogări suplimentare:

Mai există o întrebare care m-a bătut o vreme: De ce este asta prototype de Object este obiect și prototype de Function este obiect funcțional?

Aici este o explicație bună pentru asta dacă te-ai gândi la fel.

O altă întrebare care ar putea fi un mister pentru dumneavoastră până acum este: Cum primesc funcții tipurile de date primitive toString(), substr() și toFixed()? Acest lucru este bine explicat Aici.

Folosind prototype, putem face moștenirea să funcționeze cu obiectele noastre personalizate în JavaScript. Dar acesta este un subiect pentru o altă zi.

Mulțumesc pentru lectură!