Apa itu tipe? Sederhananya, tipe adalah memberikan arti tertentu pada urutan biner di memori. Misalnya, urutan biner 0100 0000 0111 0000 0001 0101 0100 1011 1100 0110 1010 0111 1110 1111 1001 1110 adalah 4643234631018606494 jika dilihat sebagai tipe bilangan bulat tak bertanda tangan 64-bit. 54 aturan representasi biner bilangan floating point (lihat Lampiran 1) ganda presisi Tipe floating point adalah 257.331.
Kebanyakan bahasa komputer menggunakan variabel untuk menyimpan dan merepresentasikan data. Beberapa bahasa menentukan tipe untuk variabel. Tipe ini tidak dapat diubah di seluruh program (baik pada waktu kompilasi atau waktu dijalankan). Sebaliknya, variabel dalam JavaScript dan beberapa bahasa lain dapat menyimpan tipe apa pun, dan mereka menggunakan variabel yang tidak diketik. Apakah tipe variabel ada tidak ada hubungannya dengan sintaksis. Misalnya, C# juga menyediakan variabel bertipe var. Namun, pernyataan berikut akan menyebabkan kesalahan di C#:
var a=1;
a="tali";
Alasannya adalah kata kunci var C# hanya menghilangkan deklarasi tipe variabel, dan secara otomatis menyimpulkan tipe variabel berdasarkan ekspresi inisialisasi, sehingga variabel var C# masih memiliki tipe. Dalam JavaScript, Anda dapat menetapkan nilai apa pun ke variabel tertentu kapan saja, sehingga variabel JavaScript tidak diketik.
Menurut metode perancangan sistem tipe bahasa komputer, dapat dibagi menjadi dua tipe: tipe kuat dan tipe lemah. Perbedaan antara keduanya terletak pada apakah konversi implisit antara tipe yang berbeda dapat transparan bagi pengguna selama penghitungan. Dari sudut pandang pengguna, jika suatu bahasa dapat secara implisit mengonversi semua tipenya, maka ketika variabel, ekspresi, dll. dilibatkan dalam operasi, meskipun tipenya salah, mereka masih bisa mendapatkan tipe yang benar melalui konversi implisit , seolah-olah semua tipe dapat melakukan semua operasi, sehingga bahasa seperti itu disebut dengan tipe yang lemah. Sebaliknya, belum tentu terdapat konversi implisit antar tipe dalam bahasa yang bertipe kuat (misalnya, C++ adalah bahasa yang bertipe kuat, namun double dan int dapat dikonversikan satu sama lain dalam C++, namun diperlukan pemeran antara double dan sembarang jenis penunjuk. )
Tipe dapat membantu pemrogram menulis program yang benar, dan tipe tersebut bertindak sebagai pembatas dalam proses penulisan program yang sebenarnya. Aturan umumnya adalah semakin kuat batasannya, semakin kecil kemungkinan kesalahannya, namun semakin sulit menulis programnya. Bahasa yang diketik dengan kuat dengan variabel yang memiliki tipe memiliki batasan yang paling kuat, dan perwakilan tipikalnya adalah C++. Bahasa dengan tipe yang lemah yang memiliki variabel yang tidak diketik memiliki batasan yang paling lemah, dengan JavaScript sebagai perwakilan yang khas. Dalam JavaScript, karena batasannya relatif lemah, kesalahan ini rentan terjadi:
var a =200;
var b="1";
var c= a+b;
Anda mungkin mengharapkan c menjadi 201, namun kenyataannya itu adalah "2001", sebuah kesalahan yang tidak pernah terjadi dalam bahasa yang diketik dengan kuat. Namun, justru karena JavaScript tidak memiliki batasan ini, JavaScript dapat dengan mudah menggabungkan tipe numerik dan string. Oleh karena itu, batasan dan fleksibilitas selalu menjadi serangkaian fitur yang perlu seimbang bagi perancang bahasa.
Tipe adalah batasan yang bekerja melalui pemeriksaan tipe. Dalam bahasa yang berbeda, pemeriksaan tipe bekerja pada tahapan yang berbeda, yang dapat dibagi menjadi pemeriksaan waktu kompilasi dan pemeriksaan waktu proses. Untuk bahasa interpretasi seperti JavaScript, terdapat tahapan yang mirip dengan proses kompilasi yaitu analisis leksikal dan analisis sintaksis. Jika pengecekan tipe bahasa interpretasi selesai pada analisis sintaksis atau tahap sebelumnya, maka dapat juga dipertimbangkan mirip dengan pemeriksaan waktu kompilasi. Jadi pernyataan yang lebih masuk akal adalah pemeriksaan tipe statis dan pemeriksaan tipe dinamis.
Menariknya, meskipun banyak bahasa memeriksa tipe pada waktu kompilasi, informasi tipenya masih dapat diperoleh saat runtime. Misalnya, C# menggunakan metadata untuk menyimpan informasi tipe. Selama runtime, pengguna dapat memperoleh dan menggunakan tipe melalui informasi refleksi.
JavaScript memprioritaskan fleksibilitas dalam setiap aspek desainnya, sehingga menggunakan pemeriksaan tipe dinamis dan tidak secara aktif memeriksa tipe kecuali ketika melakukan sedikit operasi spesifik. Anda dapat memperoleh informasi jenis variabel atau ekspresi apa pun saat runtime dan memeriksa kebenarannya melalui logika program.
Ada 9 tipe yang ditentukan dalam standar JavaScript: Penyelesaian Daftar Referensi Objek Nomor String Boolean Null Tidak Terdefinisi
Diantaranya, ketiga jenis Penyelesaian Daftar Referensi hanya digunakan selama runtime penguraian bahasa dan tidak dapat diakses langsung dari program. Ketiga jenis tersebut tidak akan diperkenalkan di sini. Di bawah ini kita dapat mempelajari keenam jenis tersebut:
Tipe Undefinisi hanya memiliki satu nilai, undefinisi, yang merupakan nilai ketika variabel tidak diberi nilai. Di JS, objek global memiliki properti tidak terdefinisi yang mewakili tidak terdefinisi tetapkan nilai ke properti global yang tidak terdefinisi untuk mengubah nilainya.
Tipe Null juga hanya memiliki satu nilai, null, namun JavaScript menyediakannya dengan kata kunci null untuk mewakili nilai unik ini. Semantik dari tipe Null adalah "referensi objek kosong".
Boolean memiliki dua nilai: benar dan salah
Interpretasi formal dari tipe String adalah urutan tipe integer 16-bit yang tidak ditandatangani, yang sebenarnya digunakan untuk mewakili informasi teks yang dikodekan dalam UTF-16.
Nomor JavaScript memiliki total nilai 18437736874454810627 (yaitu, 264-253 +3). Nomor JavaScript disimpan dalam tipe floating point presisi ganda, kecuali 9007199254740990 mewakili NaN, yang sesuai dengan IEEE 754 (lihat Lampiran 1) dan menempati 64 bit dan 8 byte.
Tipe paling kompleks dalam JavaScript adalah Objek, yang merupakan kumpulan serangkaian properti yang tidak berurutan. Fungsi adalah Objek yang mengimplementasikan properti pribadi [[panggilan]]. Host JavaScript juga dapat menyediakan beberapa objek khusus.
Saya telah membicarakan tentang tipe yang ditentukan dalam standar JS sebelumnya. Namun, masalah yang tidak dapat diabaikan adalah bahwa standar JS ditulis untuk pelaksana JS, tipe tidak harus didefinisikan sesuai dengan standar , karena JS adalah Saat melakukan operasi ., tipe non-Objek akan secara otomatis diubah menjadi objek yang sesuai, jadi "str".length sebenarnya setara dengan (new String("str")).length Bukan ide yang buruk jika keduanya memiliki tipe yang sama. Kami menggunakan beberapa fitur bahasa di JS untuk melakukan diskriminasi tipe runtime, tetapi hasil dari metode ini berbeda.
Typeof adalah operator dalam bahasa JS. Dari sudut pandang literal, ini jelas digunakan untuk mendapatkan tipe. Menurut standar JavaScript, typeof memperoleh representasi string dari nama tipe variabel. bool, number, undefinisi, objek, fungsi, dan standar JavaScript memungkinkan pelaksananya untuk menyesuaikan jenis nilai beberapa objek.
Ada daftar deskripsi dalam standar JS:
Jenis | Hasil |
Belum diartikan | "belum diartikan" |
Batal | "obyek" |
Boolean | "boolean" |
Nomor | "nomor" |
Rangkaian | "rangkaian" |
Objek (asli dan tidak mengimplementasikan [[panggilan]]) | "obyek" |
Objek (asli dan implementasi [[panggilan]]) | "fungsi" |
Objek (tuan rumah) | Tergantung pada implementasi |
Contoh berikut berasal dari Rimifon 51js, yang menunjukkan situasi di mana hasil typeof di IE menghasilkan "date" dan "unknown":
var xml=dokumen.createElement("xml");
var rs=xml.kumpulan rekaman;
rs.Fields.Append("tanggal", 7, 1);
rs.Fields.Append("bin", 205, 1);
rs.Buka();
rs.TambahBaru();
rs.Fields.Item("tanggal").Nilai = 0;
rs.Fields.Item("bin").Nilai = 21704;
rs.Perbarui();
var tanggal = rs.Fields.Item("tanggal").Nilai;
var bin = rs.Fields.Item("bin").Nilai;
rs.Tutup();
peringatan(tanggal);
peringatan(tempat sampah);
alert([jenis tanggal, jenis bin]);
coba{alert(date.getDate())}catch(err){alert(err.message)}
Sebenarnya banyak kritik terhadap metode penilaian ini yang paling dekat dengan semantik "tipe", salah satunya adalah tidak dapat membedakan objek yang berbeda. String Baru ("abc") dan Angka baru (123) tidak dapat dibedakan menggunakan typeof Pemrograman JS, sejumlah besar objek yang berbeda sering digunakan, dan typeof hanya dapat memberikan hasil "objek" yang samar-samar untuk semua objek, yang sangat mengurangi kepraktisannya.
Arti instanceof diterjemahkan ke dalam bahasa Cina sebagai "adalah turunan dari...". Secara harfiah, ini adalah istilah yang didasarkan pada pemrograman berorientasi objek berbasis kelas, dan JS sebenarnya tidak memberikan dukungan untuk pemrograman berbasis kelas pada saat itu. tingkat bahasa. Meskipun standar JavaScript tidak menyebutkan sepatah kata pun, pada kenyataannya, desain beberapa objek bawaan dan pengaturan operator semuanya mengisyaratkan cara "resmi" untuk mengimplementasikan kelas, yaitu dari menggunakan fungsi sebagai kelas, ketika operator baru bertindak. pada fungsi, Atribut prototipe fungsi diatur ke prototipe objek yang baru dibangun, dan fungsi itu sendiri digunakan sebagai konstruktor.
Oleh karena itu, objek yang dibangun dari operasi baru dengan fungsi yang sama dianggap sebagai turunan dari suatu kelas. Kesamaan yang dimiliki objek-objek ini adalah: 1. Mereka memiliki prototipe yang sama dan 2. Mereka diproses oleh konstruktor yang sama. Dan instanceof adalah operator yang memeriksa "apakah suatu instance termasuk dalam suatu kelas" sehubungan dengan cara mengimplementasikan suatu kelas. Anda juga dapat menebak bahwa sangat sulit untuk memeriksa apakah suatu objek telah diproses oleh konstruktor, tetapi lebih mudah untuk memeriksa apa prototipenya. Oleh karena itu, implementasi instanceof dipahami dari sudut pandang prototipe, yaitu periksa apakah atribut [ [prototipe]] konsisten dengan prototipe fungsi tertentu. Perhatikan bahwa [[prototype]] di sini adalah milik pribadi, yang dapat diakses menggunakan __proto__ di SpiderMonkey (yang merupakan mesin JS Firefox).
Prototipe hanya bermakna untuk tipe Objek yang dijelaskan oleh standar, jadi instanceof akan mendapatkan false untuk semua objek non-Objek, dan instanceof hanya dapat menentukan apakah objek tersebut termasuk dalam tipe tertentu, tetapi tidak dapat memperoleh tipe tersebut instanceof juga jelas. Ia dapat membedakan dirinya sendiri. Sebuah objek yang dibangun dari "kelas" yang ditentukan.
Faktanya, instanceof dapat ditipu. Meskipun atribut privat [[prototipe]] dari objek yang digunakannya tidak dapat diubah, prototipe fungsi tersebut adalah atribut publik.
fungsi KelasA(){};
fungsi KelasB(){};
var o = new ClassA();//Membangun objek kelas A
ClassB.prototype = ClassA.prototype; //Ganti ClassB.prototype
alert(o instanceof ClassB)//penipuan yang sebenarnya berhasil - -!
Object.prototype.toString awalnya sulit untuk dipanggil. Semua kelas bawaan JavaScript mencakup metode toString. Untuk objek yang dibuat oleh kelas non-bawaan, Object.prototype.toString hanya bisa mendapatkan [object Object ] yang tidak berarti. hasil. Oleh karena itu, untuk waktu yang cukup lama, efek magis dari fungsi ini belum ditemukan.
Secara standar, deskripsi Object.prototype.toString hanya 3 kalimat
1. Dapatkan atribut [[class]] dari objek ini
2. Hitung sebuah string dengan menggabungkan ketiga string "[objek", hasil(1), dan "]"
3. Kembalikan hasilnya (2).
Jelas, Object.prototype.toString sebenarnya hanya mendapatkan atribut [[class]] dari objek tersebut, tapi saya tidak tahu apakah itu disengaja. Semua objek fungsi bawaan JS String Number Array RegExp... semuanya akan digunakan saat menggunakan new untuk membuat objek. Atur atribut [[class]] sehingga atribut [[class]] dapat digunakan sebagai dasar yang baik untuk menilai jenisnya.
Karena Object.prototype.toString mengambil properti dari objek ini, Anda dapat menentukan objek ini dan kemudian mendapatkan tipenya dengan menggunakan Object.prototype.toString.call atau Object.prototype.toString.apply.
Meskipun Object.prototype.toString pintar, ia tidak dapat memperoleh tipe objek yang dibuat oleh fungsi khusus, karena fungsi khusus tidak menyetel [[kelas]], dan properti pribadi ini tidak dapat diakses dalam program. Keuntungan terbesar dari Object.prototype.toString adalah ia dapat membuat 1 dan new Number(1) menjadi tipe objek yang sama.
Namun, perlu dicatat bahwa ketika new Boolean(false) berpartisipasi dalam operasi bool, hasilnya justru kebalikan dari false. Jika keduanya dianggap bertipe sama saat ini, maka akan mudah menyebabkan kesalahan yang sulit dilakukan memeriksa.
Untuk membandingkan ketiga jenis metode penilaian di atas, saya membuat tabel sehingga setiap orang dapat memiliki perbandingan keseluruhan dari beberapa metode. Untuk memudahkan perbandingan, saya telah menyatukan hasil yang diperoleh dengan beberapa metode penilaian:
obyek | jenis | contoh | Objek.prototipe.toString | standar |
"abc" | Rangkaian | —— | Rangkaian | Rangkaian |
String baru("abc") | Obyek | Rangkaian | Rangkaian | Obyek |
fungsi halo(){} | Fungsi | Fungsi | Fungsi | Obyek |
123 | Nomor | —— | Nomor | Nomor |
Nomor baru(123) | Obyek | Nomor | Nomor | Obyek |
Array baru(1,2,3) | Obyek | Himpunan | Himpunan | Obyek |
TipeSaya baru() | Obyek | Tipe Saya | Obyek | Obyek |
batal | Obyek | —— | Obyek | Batal |
belum diartikan | Belum diartikan | —— | Obyek | Belum diartikan |
Faktanya, sulit untuk mengatakan metode mana yang lebih masuk akal. Bahkan ketentuan dalam standar hanya mencerminkan mekanisme runtime JS daripada praktik penggunaan terbaik. Pendapat pribadi saya adalah meremehkan konsep "tipe" dan lebih fokus pada batasan "bagaimana saya ingin menggunakan objek ini". Menggunakan typeof dan instanceof untuk memeriksa dapat mencapai efek yang sama dengan bahasa yang diketik dengan kuat jika diperlukan.
bit tanda: digunakan untuk mewakili tanda positif dan negatif
eksponen: digunakan untuk menyatakan bilangan pangkat
mantissa (mantissa): digunakan untuk menunjukkan akurasi