Rumah >hujung hadapan web >tutorial js >Pemahaman mendalam tentang siri JavaScript (18): Pelaksanaan ECMAScript bagi pengaturcaraan berorientasikan objek_Pengetahuan asas
Pengenalan
Bab ini adalah bahagian kedua tentang pelaksanaan berorientasikan objek ECMAScript Dalam bahagian pertama, kami membincangkan pengenalan dan perbandingan CEMAScript Jika anda belum membaca bahagian pertama, sebelum meneruskan bab ini, saya amat mengesyorkan bahawa anda membaca bahagian pertama 1 artikel, kerana artikel ini terlalu panjang (35 halaman).
Teks asal bahasa Inggeris:http://dmitrysoshnikov.com/ecmascript/chapter-7-2-oop-ecmascript-implementation/
Nota: Oleh kerana panjangnya artikel ini, ralat tidak dapat dielakkan dan sentiasa disemak.
Dalam pengenalan, kami meluaskan kepada ECMAScript Sekarang, apabila kami mengetahui pelaksanaan OOPnya, mari kita takrifkannya dengan tepat:
Jenis Data
Walaupun ECMAScript ialah bahasa ditaip secara dinamik yang lemah yang boleh menukar jenis secara dinamik, ia masih mempunyai jenis data. Dalam erti kata lain, objek mesti tergolong dalam jenis sebenar.
Terdapat 9 jenis data yang ditakrifkan dalam spesifikasi standard, tetapi hanya 6 yang boleh diakses secara langsung dalam program ECMAScript iaitu: Undefined, Null, Boolean, String, Number dan Object.
Tiga jenis lain hanya boleh diakses pada peringkat pelaksanaan (objek ECMAScript tidak boleh menggunakan jenis ini) dan digunakan dalam spesifikasi untuk menerangkan beberapa gelagat operasi dan menyimpan nilai perantaraan. 3 jenis ini ialah: Rujukan, Senarai dan Penyusunan.
Oleh itu, Rujukan digunakan untuk menerangkan operator seperti padam, jenis, dan ini, dan mengandungi objek asas dan nama sifat menerangkan kelakuan senarai parameter (dalam ungkapan baru dan panggilan fungsi); untuk menerangkan tingkah laku break, continue, return dan throw statement.
Jenis nilai primitif
Melihat kembali 6 jenis data yang digunakan dalam atur cara ECMAScript, 5 yang pertama ialah jenis nilai primitif, termasuk Undefined, Null, Boolean, String, Number dan Object.
Contoh jenis nilai primitif:
Nilai ini dilaksanakan secara langsung pada lapisan bawah Ia bukan objek, jadi tiada prototaip atau pembina.
Nota pakcik: Walaupun nilai asli ini serupa dengan nama yang biasa kita gunakan (Boolean, String, Number, Object), nilai tersebut bukanlah perkara yang sama. Oleh itu, keputusan typeof(true) dan typeof(Boolean) adalah berbeza, kerana hasil typeof(Boolean) ialah fungsi, jadi fungsi Boolean, String dan Number mempunyai prototaip (juga disebut dalam bab atribut membaca dan menulis di bawah) .
Jika anda ingin mengetahui jenis data itu, sebaiknya gunakan typeof Terdapat contoh yang perlu anda perhatikan Jika anda menggunakan typeof untuk menentukan jenis null, hasilnya adalah objek. kenapa? Kerana jenis null ditakrifkan sebagai Null.
Spesifikasi tidak membayangkan untuk menerangkan perkara ini, tetapi Brendan Eich (pencipta JavaScript) mendapati bahawa null kebanyakannya digunakan di tempat objek muncul, berbanding undefined, seperti menetapkan objek kepada rujukan null. Walau bagaimanapun, sesetengah orang dalam beberapa dokumen mengaitkannya dengan pepijat, dan meletakkan pepijat dalam senarai pepijat yang Brendan Eich turut serta dalam perbincangan Hasilnya ialah keputusan jenis null telah ditetapkan untuk membantah (walaupun 262-3 The standard mentakrifkan bahawa jenis null ialah Null, dan 262-5 telah mengubah suai standard untuk mengatakan bahawa jenis null ialah objek).
Jenis objek
Seterusnya, jenis Objek (jangan dikelirukan dengan pembina Objek, kami hanya membincangkan jenis abstrak sekarang) ialah satu-satunya jenis data yang menerangkan objek ECMAScript.
Objek ialah koleksi tidak tertib pasangan nilai kunci.
Objek ialah koleksi tidak tertib pasangan nilai kunci
Nilai utama objek dipanggil atribut dan atribut ialah bekas untuk nilai primitif dan objek lain. Jika nilai atribut ialah fungsi, kami memanggilnya kaedah.
Contohnya:
Dinamik
Seperti yang kami nyatakan dalam Bab 17, objek dalam ES adalah dinamik sepenuhnya. Ini bermakna kita boleh menambah, mengubah suai atau memadam sifat objek sesuka hati semasa program sedang dilaksanakan.
Contohnya:
Sesetengah sifat tidak boleh diubah suai - (sifat baca sahaja, sifat dipadamkan atau sifat tidak boleh dikonfigurasikan). Kami akan menerangkannya kemudian dalam sifat atribut.
Selain itu, spesifikasi ES5 menetapkan bahawa objek statik tidak boleh dilanjutkan dengan sifat baharu dan halaman sifatnya tidak boleh dipadamkan atau diubah suai. Ia adalah apa yang dipanggil objek beku, yang boleh diperolehi dengan menggunakan kaedah Object.freeze(o).
Dalam spesifikasi ES5, kaedah Object.preventExtensions(o) juga digunakan untuk menghalang sambungan, atau kaedah Object.defineProperty(o) digunakan untuk menentukan sifat:
Objek terbina dalam, objek asli dan objek hos
Perlu ambil perhatian bahawa spesifikasi juga membezakan antara objek terbina dalam, objek elemen dan objek hos.
Objek terbina dalam dan objek elemen ditakrifkan dan dilaksanakan oleh spesifikasi ECMAScript, dan perbezaan antara kedua-duanya adalah tidak ketara. Semua objek yang dilaksanakan oleh ECMAScript ialah objek asli (sesetengahnya adalah objek terbina dalam, sesetengahnya dicipta apabila program dilaksanakan, seperti objek yang ditentukan pengguna). Objek terbina dalam ialah subset objek asli yang dibina ke dalam ECMAScript sebelum program bermula (contohnya, parseInt, Match, dll.). Semua objek hos disediakan oleh persekitaran hos, biasanya penyemak imbas, dan mungkin termasuk tetingkap, amaran, dsb.
Perhatikan bahawa objek hos mungkin dilaksanakan oleh ES sendiri, mematuhi sepenuhnya semantik spesifikasi. Dari sudut pandangan ini, mereka boleh dipanggil objek "hos asli" (secepat mungkin secara teori), tetapi spesifikasi tidak mentakrifkan konsep objek "hos asli".
Objek Boolean, Rentetan dan Nombor
Selain itu, spesifikasi juga mentakrifkan beberapa kelas pembungkusan khas asli Objek ini ialah:
1. Objek Boolean
2. Objek rentetan
3. Objek digital
Objek ini dicipta melalui pembina terbina dalam yang sepadan dan mengandungi nilai asli sebagai sifat dalaman objek ini boleh menukar nilai primitif dan sebaliknya.
Selain itu, terdapat objek yang dicipta oleh pembina terbina dalam khas: Fungsi (pembina objek fungsi), Array (pembina tatasusunan) RegExp (pembina ungkapan biasa), Matematik (modul matematik), Tarikh (pembina tarikh) (bekas) , dsb. Objek ini juga merupakan nilai jenis objek Objek Perbezaannya antara satu sama lain diuruskan oleh sifat dalaman, yang kita bincangkan di bawah.
Tersurat
Untuk nilai tiga objek: objek, tatasusunan dan ungkapan biasa, mereka mempunyai pengecam singkatan yang dipanggil: pemula objek, pemula tatasusunan dan ungkapan biasa:
Perhatikan bahawa jika tiga objek di atas ditetapkan semula kepada jenis baharu, maka semantik pelaksanaan seterusnya akan digunakan mengikut jenis yang baru ditetapkan Contohnya, dalam pelaksanaan semasa Rhino dan versi lama SpiderMonkey 1.7, ia akan Objek berjaya dibuat menggunakan pembina kata kunci baharu, tetapi dalam beberapa pelaksanaan (pada masa ini Spider/TraceMonkey) semantik literal tidak semestinya berubah selepas jenis ditukar.
Tersurat ungkapan biasa dan objek RegExp
Perhatikan bahawa dalam dua contoh berikut, semantik ungkapan biasa adalah setara dalam edisi ketiga spesifikasi Regexp literal hanya wujud dalam satu ayat dan dicipta dalam peringkat penghuraian, tetapi yang dicipta oleh pembina RegExp. ialah Ia adalah objek baharu, jadi ini mungkin menyebabkan beberapa masalah Sebagai contoh, nilai lastIndex adalah salah semasa ujian:
Susun atur bersekutu
Pelbagai perbincangan statik teks, objek JavaScript (selalunya dibuat menggunakan pemula objek {}) dipanggil jadual cincang, jadual cincang atau nama mudah lain: cincang (konsep dalam Ruby atau Perl), Array pengurusan (konsep dalam PHP) , kamus (konsep dalam Python), dsb.
Hanya terdapat istilah sedemikian, terutamanya kerana strukturnya adalah serupa, iaitu, menggunakan pasangan "nilai-kunci" untuk menyimpan objek, yang benar-benar konsisten dengan struktur data yang ditakrifkan oleh teori "tatasusunan bersekutu" atau "cincang meja". Selain itu, jenis data abstrak jadual hash biasanya digunakan pada peringkat pelaksanaan.
Walau bagaimanapun, walaupun terminologi menerangkan konsep ini, ia sebenarnya satu kesilapan Dari perspektif ECMAScript: ECMAScript hanya mempunyai satu objek dan jenis serta subjenisnya, yang tidak berbeza daripada simpanan pasangan "nilai-kunci", jadi Terdapat. bukanlah konsep khusus mengenai perkara ini. Kerana sifat dalaman mana-mana objek boleh disimpan sebagai pasangan nilai kunci:
Selain itu, memandangkan objek boleh kosong dalam ECMAScript, konsep "hash" juga tidak betul di sini:
Sila ambil perhatian bahawa piawaian ES5 membenarkan kami mencipta objek tanpa prototaip (dilaksanakan menggunakan kaedah Object.create(null) Daripada perspektif ini, objek tersebut boleh dipanggil jadual cincang:
Walau bagaimanapun, walaupun dianggap bahawa "cincang" mungkin mempunyai "prototaip" (cth., kelas yang mewakilkan objek cincang dalam Ruby atau Python), dalam ECMAScript, istilah ini tidak betul kerana terdapat jurang antara kedua-dua perwakilan. Tiada perbezaan semantik (iaitu menggunakan notasi titik a.b dan a["b"] notasi).
Konsep dan semantik "atribut sifat" dalam ECMAScript tidak dipisahkan daripada "kunci", indeks tatasusunan dan kaedah Pembacaan dan penulisan sifat semua objek di sini mesti mengikut peraturan yang sama: semak rantai prototaip.
Dalam contoh Ruby berikut, kita dapat melihat perbezaan semantik:
Penukaran objek
Untuk menukar objek kepada nilai primitif, anda boleh menggunakan kaedah valueOf Seperti yang kami katakan, apabila pembina fungsi dipanggil sebagai fungsi (untuk beberapa jenis), tetapi jika kata kunci baharu tidak digunakan, objek ditukar kepada nilai primitif , yang bersamaan dengan panggilan kaedah valueOf:
Nilai lalai valueOf akan berubah mengikut jenis objek (jika tidak dibatalkan untuk sesetengah objek, ia mengembalikan ini - contohnya: Object.prototype.valueOf(), dan nilai yang dikira : Date.prototype .valueOf() mengembalikan tarikh dan masa:
Kaedah toString yang ditakrifkan pada Object.prototype mempunyai makna istimewa Ia mengembalikan nilai atribut [[Class]] dalaman yang akan kita bincangkan di bawah.
Berbanding dengan menukar kepada nilai primitif (ToPrimitive), menukar nilai kepada jenis objek juga mempunyai spesifikasi penukaran (ToObject).
Kaedah eksplisit ialah menggunakan pembina Objek terbina dalam sebagai fungsi untuk memanggil ToObject (agak serupa dengan kata kunci baharu):
Tiada peraturan am tentang memanggil pembina terbina dalam, sama ada menggunakan operator baharu atau tidak, ia bergantung kepada pembina. Contohnya, Tatasusunan atau Fungsi menghasilkan hasil yang sama apabila digunakan sebagai pembina menggunakan operator baharu atau fungsi mudah yang tidak menggunakan operator baharu:
Ciri-ciri atribut
Semua hartanah boleh mempunyai banyak atribut.
1.{ReadOnly} - Abaikan operasi tulis untuk memberikan nilai kepada harta, tetapi sifat baca sahaja boleh diubah oleh gelagat persekitaran hos - iaitu, ia bukan "nilai malar";
2.{DontEnum}——Atribut tidak boleh dihitung dengan for..in loop
3.{DontDelete}——Tingkah laku pengendali padam diabaikan (iaitu, ia tidak boleh dipadamkan);
4. {Internal} - Atribut dalaman, tiada nama (hanya digunakan pada peringkat pelaksanaan), atribut tersebut tidak boleh diakses dalam ECMAScript.
Perhatikan bahawa dalam ES5 {ReadOnly}, {DontEnum} dan {DontDelete} dinamakan semula kepada [[Boleh Ditulis]], [[Boleh Dihitung]] dan [[Boleh Dikonfigurasikan]], yang boleh dilalui secara manual melalui Object.defineProperty atau serupa kaedah untuk menguruskan hartanah ini.
Sifat dalaman dan kaedah
Objek juga boleh mempunyai sifat dalaman (sebahagian daripada tahap pelaksanaan) yang tidak boleh diakses secara langsung kepada program ECMAScript (tetapi seperti yang akan kita lihat di bawah, sesetengah pelaksanaan membenarkan akses kepada beberapa sifat sedemikian). Sifat ini diakses melalui kurungan empat segi bersarang [[ ]]. Mari kita lihat beberapa daripada mereka Penerangan sifat ini boleh didapati dalam spesifikasi.
Setiap objek harus melaksanakan sifat dan kaedah dalaman berikut:
1.[[Prototaip]] - prototaip objek (akan diperkenalkan secara terperinci di bawah)
2.[[Kelas]] - perwakilan objek rentetan (contohnya, Tatasusunan Objek, Objek Fungsi, Fungsi, dsb.);
3.[[Dapatkan]]——Kaedah untuk mendapatkan nilai atribut
4.[[Put]]——Kaedah untuk menetapkan nilai atribut
5.[[CanPut]]——Periksa sama ada atribut boleh ditulis
6.[[HasProperty]]——Periksa sama ada objek sudah mempunyai sifat ini
7.[[Padam]]——Padamkan atribut daripada objek
8.[[DefaultValue]] mengembalikan nilai asal objek (memanggil kaedah valueOf, sesetengah objek mungkin membuang pengecualian TypeError).
Nilai sifat dalaman [[Kelas]] boleh diperoleh secara tidak langsung melalui kaedah Object.prototype.toString(), yang sepatutnya mengembalikan rentetan berikut: "[objek " [[Kelas]] "]" . Contohnya:
Pembina
Jadi, seperti yang kami nyatakan di atas, objek dalam ECMAScript dicipta melalui apa yang dipanggil pembina.Pembina ialah fungsi yang mencipta dan memulakan objek yang baru dibuat.
Pembina ialah fungsi yang mencipta dan memulakan objek yang baru dibuat.
Penciptaan objek (peruntukan memori) dijaga oleh kaedah dalaman pembina [[Construct]]. Tingkah laku kaedah dalaman ini ditakrifkan dengan baik, dan semua pembina menggunakan kaedah ini untuk memperuntukkan memori untuk objek baharu.
Perhatikan bahawa kod pengguna hanya boleh diakses semasa fasa permulaan, walaupun semasa fasa permulaan kita boleh mengembalikan objek lain (mengabaikan objek tihs yang dibuat dalam fasa pertama):
[[Panggil]] ] ialah cara utama untuk membezakan objek selain daripada atribut [[Kelas]] (di sini bersamaan dengan "Fungsi"), jadi atribut dalaman [[Panggil]] objek dipanggil sebagai fungsi. Menggunakan operator jenis pada objek sedemikian mengembalikan "fungsi". Walau bagaimanapun, ia berkaitan terutamanya dengan objek asli Dalam beberapa kes, pelaksanaan menggunakan typeof untuk mendapatkan nilai adalah berbeza. Contohnya: kesan window.alert (...) dalam IE:
Kaedah dalaman [[Construct]] diaktifkan dengan menggunakan pembina dengan operator baharu Seperti yang kami katakan, kaedah ini bertanggungjawab untuk peruntukan memori dan penciptaan objek. Jika tiada parameter, kurungan untuk memanggil pembina juga boleh ditinggalkan:
Mari kita kaji algoritma penciptaan objek.
Algoritma untuk penciptaan objek
Kelakuan kaedah dalaman [[Construct]] boleh diterangkan seperti berikut:
Sila ambil perhatian dua ciri utama:
1. Pertama, prototaip objek yang baru dicipta diperoleh daripada atribut prototaip fungsi pada saat semasa (ini bermakna prototaip dua objek yang dicipta yang dicipta oleh pembina yang sama boleh berbeza kerana atribut prototaip bagi fungsinya juga boleh berbeza) .
2. Kedua, seperti yang kami nyatakan di atas, jika [[Panggil]] mengembalikan objek apabila objek dimulakan, ini betul-betul hasil yang digunakan untuk keseluruhan operator baharu:
Prototaip
Setiap objek mempunyai prototaip (kecuali beberapa objek sistem). Komunikasi prototaip dijalankan melalui sifat prototaip [[Prototaip]] dalaman, tersirat, dan tidak boleh diakses secara langsung Prototaip boleh menjadi objek atau nilai nol.
Pembina hartanah
Terdapat dua titik pengetahuan penting dalam contoh di atas Yang pertama adalah mengenai atribut prototaip atribut pembina fungsi Dalam algoritma penciptaan fungsi, kita tahu bahawa atribut pembina ditetapkan kepada atribut prototaip fungsi semasa fasa penciptaan fungsi , nilai atribut pembina adalah rujukan penting kepada fungsi itu sendiri:
Biasanya dalam kes ini, terdapat salah faham: sifat pembina pembina adalah salah sebagai harta objek yang baru dibuat itu sendiri, tetapi, seperti yang kita lihat, harta ini tergolong dalam prototaip dan diakses melalui warisan.
Dengan mewarisi contoh atribut pembina, anda secara tidak langsung boleh mendapatkan rujukan kepada objek prototaip:
Tetapi sila ambil perhatian bahawa atribut pembina dan prototaip fungsi boleh ditakrifkan semula selepas objek dicipta. Dalam kes ini, objek kehilangan mekanisme yang diterangkan di atas. Jika anda mengedit prototaip elemen melalui atribut prototaip fungsi (menambah objek baharu atau mengubah suai objek sedia ada), anda akan melihat atribut yang baru ditambah pada contoh itu.
Walau bagaimanapun, jika kita menukar sepenuhnya sifat prototaip fungsi (dengan memperuntukkan objek baharu), rujukan kepada pembina asal hilang, kerana objek yang kita cipta tidak termasuk harta pembina:
Perhatikan bahawa walaupun atribut pembina telah dipulihkan secara manual, berbanding dengan prototaip asal yang hilang, ciri {DontEnum} tidak lagi tersedia, yang bermaksud pernyataan gelung for..in dalam A.prototype tidak disokong, tetapi dalam edisi ke-5 spesifikasi , menyediakan keupayaan untuk mengawal keadaan terbilang yang boleh dikira melalui atribut [[Enumerable]].
Prototaip eksplisit dan atribut [[Prototaip]] tersirat
Secara amnya, adalah tidak betul untuk merujuk prototaip objek secara eksplisit melalui atribut prototaip fungsi Ia merujuk kepada objek yang sama, atribut [[Prototaip]] objek:
a.[[Prototaip]] ----> Prototaip <---- A.prototaip
Selain itu, nilai [[Prototaip]] contoh sememangnya diperoleh daripada atribut prototaip pembina.
Walau bagaimanapun, penyerahan atribut prototaip tidak akan menjejaskan prototaip objek yang telah dibuat (ia hanya akan terjejas apabila atribut prototaip pembina berubah, maksudnya, hanya objek yang baru dibuat akan mempunyai prototaip baharu dan objek yang telah dibuat masih akan mempunyai prototaip baharu Rujukan kepada prototaip lama yang asal (prototaip ini tidak boleh diubah suai lagi).
Contohnya:
Peraturan utama di sini ialah: prototaip objek dicipta apabila objek dibuat, dan tidak boleh diubah suai kepada objek baharu selepas itu Jika ia masih merujuk kepada objek yang sama, ia boleh dirujuk melalui prototaip eksplisit daripada pembina. Selepas objek dicipta, hanya sifat prototaip boleh ditambah atau diubah suai.
Atribut __proto__ bukan standard
Walau bagaimanapun, sesetengah pelaksanaan, seperti SpiderMonkey, menyediakan atribut eksplisit __proto__ bukan standard untuk merujuk prototaip objek:
Objek bebas daripada pembina
Oleh kerana prototaip contoh adalah bebas daripada pembina dan atribut prototaip pembina, pembina boleh dipadamkan selepas menyelesaikan kerja utamanya (membuat objek). Objek prototaip terus wujud dengan merujuk atribut [[Prototaip]]:
Ciri-ciri instanceof operator
Kami memaparkan prototaip rujukan melalui atribut prototaip pembina, yang berkaitan dengan pengendali instanceof. Operator ini berfungsi dengan rantai prototaip, bukan pembina Dengan mengambil kira perkara ini, selalunya berlaku salah faham apabila mengesan objek:
Mari kita lihat contoh ini:
Sebaliknya, objek boleh dibuat oleh pembina, tetapi jika atribut [[Prototaip]] objek dan nilai atribut prototaip pembina ditetapkan kepada nilai yang sama, instanceof akan kembali benar apabila disemak:
Prototaip boleh menyimpan kaedah dan berkongsi sifat
Prototaip digunakan dalam kebanyakan program untuk menyimpan kaedah objek, keadaan lalai dan sifat objek kongsi.
Sebenarnya, objek boleh mempunyai keadaannya sendiri, tetapi kaedahnya selalunya sama. Oleh itu, kaedah biasanya ditakrifkan dalam prototaip untuk pengoptimuman memori. Ini bermakna semua kejadian yang dibuat oleh pembina ini boleh berkongsi kaedah ini.
Baca dan tulis atribut
Seperti yang kami nyatakan, membaca dan menulis nilai sifat adalah melalui kaedah dalaman [[Get]] dan [[Put]]. Kaedah dalaman ini diaktifkan melalui pengakses sifat: notasi titik atau notasi indeks:
Kaedah [[Dapatkan]]
[[Get]] juga akan menanyakan sifat daripada rantai prototaip, jadi sifat dalam prototaip juga boleh diakses melalui objek.
O.[[Dapatkan]](P):
Nota: Operator dalam juga boleh bertanggungjawab untuk mencari sifat (ia juga akan mencari rantai prototaip):
Kaedah [[Put]]
Kaedah[[Put]] boleh mencipta dan mengemas kini sifat objek itu sendiri dan menutup sifat nama yang sama dalam prototaip.
O.[[Put]](P, V):
// Contohnya, panjang atribut ialah baca sahaja, mari cuba tutup panjangnya
fungsi SuperString() {
/* tiada */
}
SuperString.prototype = new String("abc");
var foo = SuperString baharu();
console.log(foo.length); // 3, panjang "abc"
// Percubaan untuk menutup
foo.length = 5;
console.log(foo.length); // Pegun 3
Akses harta
Kaedah dalaman [[Get]] dan [[Put]] diaktifkan melalui notasi titik atau pengindeksan dalam ECMAScript Jika pengecam atribut ialah nama yang sah, ia boleh diakses melalui ".", dan pengindeksan Parti berjalan secara dinamik. nama yang ditentukan.
Terdapat ciri yang sangat penting di sini - pengakses harta sentiasa menggunakan spesifikasi ToObject untuk merawat nilai di sebelah kiri "." Penukaran tersirat ini berkaitan dengan pepatah "semuanya dalam JavaScript adalah objek" (namun, seperti yang kita sedia maklum, tidak semua nilai dalam JavaScript adalah objek).
Jika pengakses atribut digunakan untuk mengakses nilai asal, nilai asal akan dibalut oleh objek (termasuk nilai asal) sebelum mengakses, dan kemudian atribut akan diakses melalui objek yang dibalut selepas atribut diakses , objek yang dibalut akan dipadamkan.
Contohnya:
Jawapannya mudah:
Pertama sekali, seperti yang kami katakan, selepas menggunakan pengakses harta, ia bukan lagi nilai asal, tetapi objek perantaraan yang dibalut (keseluruhan contoh menggunakan Nombor(a) baharu), dan kaedah toString dihantar pada ini masa Ditemui dalam rantaian prototaip:
Kami melihat bahawa dalam langkah 3, objek yang dibalut dipadamkan dan halaman sifat yang baru dibuat dipadamkan - memadamkan objek pembalut itu sendiri.
Apabila menggunakan [[Get]] untuk mendapatkan nilai ujian, objek pembungkusan dicipta semula, tetapi kali ini objek yang dibalut tidak lagi mempunyai atribut ujian, jadi undefined dikembalikan:
Warisi
Kami tahu bahawa ECMAScript menggunakan warisan delegasi berasaskan prototaip. Rantaian dan prototaip telah pun disebut dalam rantaian prototaip. Malah, semua pelaksanaan delegasi dan carian serta analisis rantaian prototaip dipekatkan ke dalam kaedah [[Get]].
Jika anda memahami sepenuhnya kaedah [[Dapatkan]], maka persoalan pewarisan dalam JavaScript akan menjadi penjelasan sendiri.
Apabila saya sering bercakap tentang warisan dalam JavaScript di forum, saya sentiasa menggunakan satu baris kod untuk menunjukkannya, sebenarnya, kita tidak perlu mencipta sebarang objek atau fungsi kerana bahasa itu sudah berdasarkan warisan adalah seperti berikut:
1 Mula-mula, buat objek pembungkusan daripada nilai asal 1 melalui Nombor(1)
baharu
2. Kemudian kaedah toString diwarisi daripada objek pembungkusan ini
Mengapa ia diwarisi? Oleh kerana objek dalam ECMAScript boleh mempunyai sifatnya sendiri, objek pembalut dalam kes ini tidak mempunyai kaedah toString. Jadi ia mewarisi daripada prinsip, iaitu Number.prototype.
Perhatikan terdapat kehalusan, dua titik dalam contoh di atas bukanlah ralat. Titik pertama mewakili bahagian perpuluhan dan titik kedua ialah pengakses atribut:
Rantai Prototaip
Mari tunjukkan cara membuat rantai prototaip untuk objek yang ditentukan pengguna, ia sangat mudah:
Kaedah ini mempunyai dua ciri:
Pertama, B.prototype akan mengandungi atribut x. Pada pandangan pertama ini mungkin kelihatan tidak betul, anda mungkin berfikir bahawa sifat x ditakrifkan dalam A dan bahawa pembina B menjangkakannya juga. Walaupun warisan prototaip tiada masalah dalam keadaan biasa, pembina B kadangkala tidak memerlukan atribut x Berbanding dengan warisan berasaskan kelas, semua atribut disalin ke subkelas turunan.
Walau bagaimanapun, jika terdapat keperluan (untuk mensimulasikan warisan berasaskan kelas) untuk menetapkan atribut x kepada objek yang dicipta oleh pembina B, terdapat beberapa cara, salah satunya akan kami tunjukkan kemudian.
Kedua, ini bukan ciri tetapi kelemahan - apabila prototaip subkelas dicipta, kod pembina juga dilaksanakan, dan kita dapat melihat bahawa mesej "A.[[Panggil]] diaktifkan" dipaparkan dua kali - Apabila menggunakan pembina A untuk mencipta objek dan menetapkannya kepada sifat B.prototype, adegan lain ialah apabila objek mencipta dirinya sendiri!
Contoh berikut adalah lebih kritikal, pengecualian yang dilemparkan oleh pembina kelas induk: Mungkin ia perlu diperiksa apabila objek sebenar dibuat, tetapi jelas, kes yang sama, iaitu, apabila menggunakan objek induk ini sebagai prototaip Sesuatu akan berlaku.
Selain itu, mempunyai terlalu banyak kod dalam pembina kelas induk juga merupakan satu kelemahan.
Untuk menyelesaikan "fungsi" dan masalah ini, pengaturcara menggunakan corak standard rantaian prototaip (ditunjukkan di bawah.