TLDR
Paksaan tipe, atau konversi tipe implisit, memungkinkan pengetikan lemah dan digunakan di seluruh JavaScript. Kebanyakan operator (dengan pengecualian penting dari operator kesetaraan yang ketat ===dan !==), dan operasi pemeriksaan nilai (misalnya if(value)...), akan memaksa nilai yang diberikan kepada mereka, jika jenis nilai tersebut tidak segera kompatibel dengan operasi.
Mekanisme tepat yang digunakan untuk memaksa nilai bergantung pada ekspresi yang dievaluasi. Dalam pertanyaan, operator penjumlahan sedang digunakan.
Operator penjumlahan pertama-tama akan memastikan kedua operan adalah primitif, yang, dalam hal ini, melibatkan pemanggilan valueOfmetode. The toStringMetode ini tidak disebut dalam hal ini karena ditimpa valueOfmetode pada objek xmengembalikan nilai primitif.
Kemudian, karena salah satu operan yang dimaksud adalah string, maka kedua operan tersebut akan diubah menjadi string. Proses ini menggunakan abstrak, operasi internal ToString(catatan: huruf besar), dan berbeda dari toStringmetode pada objek (atau rantai prototipe).
Akhirnya, string yang dihasilkan digabungkan.
Detail
Pada prototipe setiap objek fungsi konstruktor yang sesuai dengan setiap jenis bahasa dalam JavaScript (mis. Number, BigInt, String, Boolean, Symbol, dan Object), ada dua metode: valueOfdan toString.
Tujuannya valueOfadalah untuk mengambil nilai primitif yang terkait dengan suatu objek (jika ada). Jika sebuah objek tidak memiliki nilai primitif yang mendasari, maka objek tersebut dikembalikan begitu saja.
Jika valueOfdipanggil terhadap primitif, maka primitif tersebut otomatis dimasukkan ke dalam kotak dengan cara normal, dan nilai primitif yang mendasarinya dikembalikan. Perhatikan bahwa untuk string, nilai primitif yang mendasari (yaitu nilai yang dikembalikan oleh valueOf) adalah representasi string itu sendiri.
Kode berikut menunjukkan bahwa valueOfmetode mengembalikan nilai primitif yang mendasari dari objek pembungkus, dan ini menunjukkan bagaimana contoh objek yang tidak dimodifikasi yang tidak sesuai dengan primitif, tidak memiliki nilai primitif untuk dikembalikan, jadi mereka hanya mengembalikan dirinya sendiri.
console.log(typeof new Boolean(true)) // 'object'
console.log(typeof new Boolean(true).valueOf()) // 'boolean'
console.log(({}).valueOf()) // {} (no primitive value to return)
Tujuan dari toString, di sisi lain, adalah mengembalikan representasi string dari suatu objek.
Sebagai contoh:
console.log({}.toString()) // '[object Object]'
console.log(new Number(1).toString()) // '1'
Untuk sebagian besar operasi, JavaScript akan secara diam-diam mencoba mengonversi satu atau lebih operan ke jenis yang diperlukan. Perilaku ini dipilih untuk membuat JavaScript lebih mudah digunakan. JavaScript awalnya tidak memiliki pengecualian , dan ini mungkin juga berperan dalam keputusan desain ini. Jenis konversi jenis implisit ini disebut pemaksaan jenis, dan ini adalah dasar dari sistem jenis JavaScript yang longgar (lemah). Aturan rumit di balik perilaku ini dimaksudkan untuk memindahkan kerumitan typecasting ke dalam bahasa itu sendiri, dan keluar dari kode Anda.
Selama proses koersif, ada dua mode konversi yang dapat terjadi:
- Konversi objek menjadi primitif (yang mungkin melibatkan konversi tipe itu sendiri), dan
- Konversi langsung ke jenis tertentu misalnya, menggunakan fungsi objek konstruktor dari salah satu tipe primitif (yaitu.
Number(), Boolean(), String()Dll)
Konversi Menjadi Primitif
Ketika mencoba untuk mengubah tipe non-primitif menjadi primitif untuk dioperasikan, operasi abstrak ToPrimitivedipanggil dengan "petunjuk" opsional dari 'nomor', atau 'string'. Jika petunjuk dihilangkan, petunjuk default adalah 'nomor' (kecuali jika @@toPrimitivemetode telah diganti). Jika petunjuknya adalah 'string', maka toStringdicoba dulu, dan valueOfkedua jika toStringtidak mengembalikan primitif. Lain, sebaliknya. Petunjuknya tergantung pada operasi yang meminta konversi.
Operator tambahan tidak memberikan petunjuk, jadi valueOfdicoba dulu. Operator pengurangan memberikan petunjuk 'angka', jadi valueOfcoba dulu. Satu-satunya situasi yang dapat saya temukan dalam spesifikasi di mana petunjuknya adalah 'string' adalah:
Object#toString
- Operasi abstrak
ToPropertyKey, yang mengubah argumen menjadi nilai yang dapat digunakan sebagai kunci properti
Konversi Jenis Langsung
Setiap operator memiliki aturannya sendiri untuk menyelesaikan operasinya. Operator tambahan pertama-tama akan digunakan ToPrimitiveuntuk memastikan setiap operand adalah primitif; kemudian, jika salah satu operand adalah string, maka dengan sengaja akan memanggil operasi abstrak ToStringpada setiap operan, untuk menyampaikan perilaku penggabungan string yang kita harapkan dengan string. Jika, setelah ToPrimitivelangkah, kedua operan bukan string, maka dilakukan penjumlahan aritmatika.
Tidak seperti penjumlahan, operator pengurangan tidak memiliki perilaku kelebihan beban, sehingga akan memanggil toNumericsetiap operan yang telah mengonversinya terlebih dahulu menjadi penggunaan primitif ToPrimitive.
Begitu:
1 + 1 // 2
'1' + 1 // '11' Both already primitives, RHS converted to string, '1' + '1', '11'
1 + [2] // '12' [2].valueOf() returns an object, so `toString` fallback is used, 1 + String([2]), '1' + '2', 12
1 + {} // '1[object Object]' {}.valueOf() is not a primitive, so toString fallback used, String(1) + String({}), '1' + '[object Object]', '1[object Object]'
2 - {} // NaN {}.valueOf() is not a primitive, so toString fallback used => 2 - Number('[object Object]'), NaN
+'a' // NaN `ToPrimitive` passed 'number' hint), Number('a'), NaN
+'' // 0 `ToPrimitive` passed 'number' hint), Number(''), 0
+'-1' // -1 `ToPrimitive` passed 'number' hint), Number('-1'), -1
+{} // NaN `ToPrimitive` passed 'number' hint', `valueOf` returns an object, so falls back to `toString`, Number('[Object object]'), NaN
1 + 'a' // '1a' Both are primitives, one is a string, String(1) + 'a'
1 + {} // '1[object Object]' One primitive, one object, `ToPrimitive` passed no hint, meaning conversion to string will occur, one of the operands is now a string, String(1) + String({}), `1[object Object]`
[] + [] // '' Two objects, `ToPrimitive` passed no hint, String([]) + String([]), '' (empty string)
1 - 'a' // NaN Both are primitives, one is a string, `ToPrimitive` passed 'number' hint, 1-Number('a'), 1-NaN, NaN
1 - {} // NaN One primitive, one is an object, `ToPrimitive` passed 'number' hint, `valueOf` returns object, so falls back to `toString`, 1-Number([object Object]), 1-NaN, NaN
[] - [] // 0 Two objects, `ToPrimitive` passed 'number' hint => `valueOf` returns array instance, so falls back to `toString`, Number('')-Number(''), 0-0, 0
Perhatikan bahwa Dateobjek intrinsik itu unik, karena itu adalah satu-satunya intrinsik yang mengganti @@toPrimitivemetode default , di mana petunjuk default dianggap sebagai 'string' (bukan 'number'). Alasan untuk memiliki ini, adalah agar Dateinstance diterjemahkan ke string yang dapat dibaca secara default, bukan nilai numeriknya, demi kenyamanan programmer. Anda dapat menimpa objek @@toPrimitiveAnda sendiri menggunakan Symbol.toPrimitive.
Grid berikut menunjukkan hasil pemaksaan untuk operator persamaan abstrak ( ==) ( sumber ):

Lihat juga .
window.console.log (x);ataualert (x);?