Untuk memahami prototipe dalam JS, Anda harus terlebih dahulu memahami konsep -konsep berikut
1. Segala sesuatu di JS adalah sebuah objek
2. Segala sesuatu dalam JS berasal dari objek, yaitu, titik akhir dari rantai prototipe semua hal menunjuk ke objek. Prototipe
// ["Konstruktor", "Tostring", "Tolocalestring", "Valueof", "HasownProperty", "Isprototypeof", // "PropertyAnumerable", "__DefineGetter__", "__LookUpgetter__", "__Definesetter________________________________________________________" "" "" "" console.log (object.getOwnPropertynames (object.prototype));
3. Hubungan halus antara konstruktor dan instance (objek) di JS
Konstruktor mendefinisikan prototipe untuk menyetujui spesifikasi contoh mereka, dan kemudian membangun contoh melalui yang baru. Fungsinya adalah menghasilkan objek.
Konstruktor (Metode) itu sendiri adalah instance dari metode (fungsi), sehingga dapat juga ditemukan untuk __proTo __ (protochain)
Objek / fungsi f () {} Ini adalah konstruktor, satu disediakan oleh JS asli API, dan yang lainnya disesuaikan
Objek baru () / baru f () adalah instance
Contoh -contoh hanya dapat dilihat "hanya" untuk mengetahui prototipe apa yang dibuat berdasarkan.
Prototipe yang "tidak dapat" mendefinisikan kembali instance dan kemudian menipu dirinya sendiri untuk membuat instance dari instance.
Berlatihlah untuk menghasilkan pengetahuan sejati, dan hanya dengan mengamati/berpikir diri Anda dapat benar -benar memahami:
// mari kita lihat apa konstruktor itu // function kosong () {} function kosong () {} console.log (function.prototype, function .__ proto__); // objek {} function kosong () {} console.log (objek.prototype, objek .__ proto__); fungsi f () {} // f {} function kosong () {} console.log (f.prototype, f .__ proto__);Anda mungkin pusing, mari kita hancurkan.
prototipe
Format output prototipe adalah: prototipe nama konstruktor
Pertama, mari kita lihat objek apa. Output Prototype?
Objek {} -> Objek sebelumnya adalah nama konstruktor, dan yang berikutnya mewakili prototipe. Berikut adalah {}, yaitu, instance dari objek objek (objek kosong)
Kemudian f {} kami memahami apa artinya. F adalah nama konstruktor, dan prototipe juga merupakan objek kosong
// Mari kita lihat contoh yang dibangun oleh konstruktor var o = objek baru (); // var o = {}; // objek yang tidak ditentukan {} console.log (o.prototype, o .__ proto__); fungsi f () {} var i = new f (); // f {} console.log (i.prototype, i .__ proto__);Mari kita sedikit lebih dalam dan tentukan prototipe F untuk melihat apa yang akan terjadi?
fungsi f () {} f.prototype.a = function () {}; var i = f () baru; // tidak terdefinisi f {a: function} console.log (i.prototype, i .__ proto__);Dengan cara ini, kita dapat dengan jelas melihat bahwa saya dibangun dari F, prototipe adalah {a: function}, yang berarti bahwa metode a telah ditambahkan ke prototipe objek kosong asli.
Mari kita ubah situasinya, apa yang akan terjadi jika prototipe yang sepenuhnya mencakup F?
function f () {} f.prototype = {a: function () {}}; var i = f () baru; // objek yang tidak ditentukan {a: function} console.log (i.prototype, i .__ proto__);Hei ~ Mengapa itu menunjukkan di sini bahwa saya dibangun dari objek? TIDAK!
Karena kami benar -benar menimpa prototipe F, pada kenyataannya, kami menentukan prototipe sebagai objek {a: function}, tetapi ini akan menyebabkan informasi konstruktor asli hilang dan menjadi konstruktor yang ditentukan oleh objek {a: function}.
Jadi apa konstruktor objek {a: function}?
Karena objek {a: function} sebenarnya relatif terhadap
var o = {a: function () {}} // objek baruMaka konstruktor O tentu saja merupakan objek
Mari kita perbaiki kesalahan ini
function f () {} f.prototype = {a: function () {}} // spesifikasi ulang konstruktor yang benar f.prototype.constructor = f; var i = f () baru; // f {a: function, constructor: function} console.log (i.prototype, i .__ proto__);Sekarang Anda bisa mendapatkan informasi prototipe yang benar lagi ~
Rantai prototipe
Lalu mari kita lihat rantai prototipe apa itu?
Sederhananya, itu sama dengan hubungan warisan (rantai) di OOP. Cari lapisan demi lapis sampai objek terakhir.prototype
Yang paling penting adalah mencari tahu apa hal -hal di JS (instance) objek. Ini sederhana, semua yang ada di JS adalah objek!
Maka kita perlu mengetahui bahwa objek apa pun memiliki prototipe!
Lalu mari kita buktikan:
Object // Ini adalah fungsi, fungsi adalah objek instance dari fungsi, jadi ini adalah objek .__ proto__ == function.prototype // Kemudian prototipe objek, true // Ini adalah objek biasa, jadi instance objek milik function.prototype .__ proto__ == objek.prototype // true // Ini sudah menjadi top level. Object.prototype .__ Proto__ == NULL // Fungsi True // Ini juga fungsi, ya! Function .__ proto__ == function.prototype // Fungsi true a () {} // Ini adalah fungsi khusus, dan masih merupakan fungsi, itu benar! A .__ proto__ == function.prototype // fungsi apa pun yang merupakan instance fungsi, jadi apakah prototipe a? var a = new a () a .__ proto__ == a.prototype // instance a dibangun oleh konstruktor A, sehingga prototipe a ditentukan oleh atribut prototipe A.Prototype .__ proto__ == objek.prototipe // Contoh objek biasa adalah objek.Prototipe dan __proto__
Setiap objek berisi __proto__ yang menunjuk ke "prototipe" objek.
Yang serupa adalah bahwa setiap fungsi berisi prototipe. Untuk apa objek prototipe ini?
Mari kita lihat kode berikut, menggunakan konstruktor untuk membuat objek (di atas adalah membuat objek dalam bentuk bentuk literal).
function foo () {}; var foo = new foo (); console.log (foo .__ proto__);Bayangkan saja, apa yang akan ditunjukkan oleh __proto__ dari objek foo ini?
Objek yang berisi atribut konstruktor? Tidak masalah jika Anda tidak terlalu memahaminya. Cetak atribut prototipe dari fungsi FOO dan bandingkan dengan Anda untuk mengetahui.
function foo () {}; var foo = new foo (); console.log (foo .__ proto __); console.log (foo.prototype); console.log (foo .__ proto__ === foo.prototype);Ternyata __proto__ dari objek foo yang keluar dari hanya titik baru ke prototipe fungsi foo.
foo .__ proto__ -> foo.prototype
Apa gunanya merancang JS seperti ini? Mengingat apa yang disebutkan di atas, di dunia JS, objek tidak dibuat berdasarkan kelas (cetakan), tetapi berasal dari prototipe (objek lain).
Ketika kami melakukan operasi baru untuk membuat objek baru, kami tidak akan masuk jauh ke dalam implementasi spesifik operasi baru, tetapi kami yakin satu hal - yaitu, kami menunjuk pada objek prototipe untuk objek baru __Proto__.
Hanya kode ini
function foo () {}; var foo = new foo ();Siapa foo .__ proto__ menunjuk ke? Mengapa Anda tidak bisa menunjuk ke fungsi foo itu sendiri? Meskipun fungsinya juga merupakan objek, saya akan membicarakannya secara rinci jika Anda memiliki kesempatan. Tetapi tentu saja tidak tepat untuk menunjukkan foo .__ proto__foo, karena foo adalah fungsi dengan banyak kode logis. Sebagai objek, ia tidak memiliki arti untuk mewarisi pemrosesan logis. Apa yang ingin diwariskan adalah atribut dari "objek prototipe".
Oleh karena itu, setiap fungsi akan secara otomatis menghasilkan objek prototipe, dan __proto__ dari objek yang baru dari fungsi ini menunjuk ke prototipe fungsi ini.
foo .__ proto__ -> foo.prototype
Meringkaskan
Setelah mengatakan begitu banyak, saya masih belum menjelaskannya sepenuhnya, jadi lebih baik berada di gambar sebelumnya. Saya telah merujuk gambar dari netizen lain, tetapi saya selalu merasa bahwa saya tidak menjelaskan dengan jelas, jadi saya sendiri menggambar. Jika saya pikir milik saya bagus, tolong menyukainya! (Saya telah mencoba yang terbaik untuk menggambarnya).
Mari kita ambil gambar ini dan ingat fakta -fakta berikut:
1. Ada atribut _proto_ di setiap objek.
Tidak ada konsep kelas (jamur) di dunia JS. Objek berasal dari objek lain (proto), sehingga akan ada atribut _proto_ di setiap objek yang menunjuk ke objek prototipe. (Lihat objek OBJ yang didefinisikan dalam bentuk literal di sudut kiri atas. Ini membuka ruang untuk menyimpan properti objek sendiri dalam memori, dan menghasilkan _proto_ yang menunjuk ke prototipe - objek prototipe tingkat atas.)
2. Setiap fungsi memiliki properti prototipe.
Mengapa "konstruktor" disebut konstruktor? Karena ingin membuat objek. Jadi menurut fakta pertama di atas, siapa atribut _proto_ dari objek baru yang dibangun menunjuk? Anda tidak dapat menunjuk pada konstruktor itu sendiri. Meskipun juga merupakan objek, Anda tidak ingin objek baru mewarisi properti dan metode fungsi. Oleh karena itu, setiap konstruktor akan memiliki atribut prototipe, menunjuk ke objek sebagai prototipe objek baru yang dibangun oleh konstruktor ini.
3. Fungsi juga merupakan objek.
Setiap fungsi memiliki beberapa sifat dan metode umum, seperti apply ()/call (), dll. Tetapi bagaimana metode umum ini diwarisi? Bagaimana fungsi dibuat? Bayangkan saja, semuanya adalah objek, termasuk fungsi, dan merupakan objek yang dibangun melalui konstruktor. Kemudian, menurut fakta kedua di atas, setiap fungsi juga akan memiliki prototipe yang menunjuk ke konstruktornya. Fungsi konstruktor ini adalah fungsi, dan semua fungsi dalam JS dibangun dari fungsi. Properti umum dan metode fungsi disimpan pada fungsi objek prototipe.prototype.