Tweet terbaru berisi cuplikan JavaScript ini.
Dapatkah seseorang tolong jelaskan apa yang terjadi di dalamnya langkah demi langkah?
> function dis() { return this }
undefined
> five = dis.call(5)
Number {[[PrimitiveValue]]: 5}
> five.wtf = 'potato'
"potato"
> five.wtf
"potato"
> five * 5
25
> five.wtf
"potato"
> five++
5
> five.wtf
undefined
> five.wtf = 'potato?'
"potato?"
> five.wtf
undefined
> five
6
Secara khusus, tidak jelas bagi saya:
- mengapa hasilnya
dis.call(5)
adalahNumber
dengan beberapa jenis[[PrimitiveValue]]
properti, tetapi hasilfive++
danfive * 5
tampaknya hanya angka biasa5
dan25
(bukanNumber
s) - mengapa
five.wtf
properti hilang setelahfive++
kenaikan - mengapa
five.wtf
properti tidak lagi dapat diselesaikan setelahfive++
kenaikan, meskipunfive.wtf = 'potato?'
penugasan tampaknya menetapkan nilai.
javascript
Nathan Long
sumber
sumber
++
tampaknya mempengaruhi tipe yang mendasarinyaPre
vsPost
kenaikan? Setelah perkalian, itu lagi-lagi sebuahNumber
objek yang tidak memilikiwtf
properti ... Tapi tetap saja itu adalahobject
karenanya ia dapat memilikiproperties
..dis
dengandis.call(5)
, ini membungkus nomor primitif5
menjadi objek bertipeNumber
yang berisi5
, sehingga objek ini dapat dikembalikan sebagaithis
objek. The++
bertobat itu kembali ke nomor primitif yang tidak dapat berisi properti, sehinggawtf
mulai terdefinisi.Jawaban:
OP disini. Lucu melihat ini di Stack Overflow :)
Sebelum melangkah melalui perilaku, penting untuk memperjelas beberapa hal:
Nilai angka dan objek Angka (
a = 3
vsa = new Number(3)
) sangat berbeda. Satu adalah primitif, yang lain adalah objek. Anda tidak dapat menetapkan atribut ke primitif, tetapi Anda bisa untuk objek.Pemaksaan di antara keduanya adalah implisit.
Sebagai contoh:
Setiap Ekspresi memiliki nilai balik. Ketika REPL membaca dan mengeksekusi ekspresi, inilah yang ditampilkannya. Nilai pengembalian seringkali tidak berarti apa yang Anda pikirkan dan menyiratkan hal-hal yang tidak benar.
Baiklah, ini dia.
Janji.
Tentukan fungsi
dis
dan panggil dengan5
. Ini akan menjalankan fungsi dengan5
sebagai konteks (this
). Di sini ia dipaksa dari nilai Number ke objek Number. Sangat penting untuk dicatat bahwa jika kita dalam mode ketat ini tidak akan terjadi .Sekarang kita mengatur atribut
five.wtf
untuk'potato'
, dan dengan lima sebagai objek, cukup yakin ia menerima tugas sederhana .Dengan
five
sebagai objek, saya memastikan masih dapat melakukan operasi aritmatika sederhana. Bisa. Apakah atributnya masih melekat? Iya.Giliran.
Sekarang kita periksa
five++
. Trik dengan kenaikan postfix adalah bahwa seluruh ekspresi akan mengevaluasi terhadap nilai asli dan kemudian meningkatkan nilai. Sepertinyafive
masih lima, tapi benar-benar ekspresi dievaluasi menjadi lima, kemudian diaturfive
ke6
.Tidak hanya
five
diatur6
, tetapi dipaksa kembali ke nilai Number, dan semua atribut hilang. Karena primitif tidak dapat memiliki atribut,five.wtf
tidak ditentukan.Saya lagi mencoba untuk menetapkan kembali atribut
wtf
kefive
. Nilai pengembalian menyiratkan itu tetap, tetapi sebenarnya bukan karenafive
merupakan nilai angka, bukan objek angka. Ekspresi dievaluasi'potato?'
, tetapi ketika kami memeriksa kami melihat itu tidak ditugaskan.Prestise.
Sejak peningkatan postfix,
five
telah6
.sumber
int
danInteger
, misalnya. Saya berasumsi ini adalah agar Anda dapat membuat suatu fungsidoSomething(Object)
, dan masih dapat memberikannya primitif. Primitif akan dikonversi ke kelas terkait mereka dalam kasus ini. Tapi JS tidak terlalu peduli dengan tipe, jadi alasannya mungkin sesuatu yang lain++
dilakukan adalah menerapkan ToNumber ke nilai . Bandingkan kasus serupa dengan string: jika sudahx="5"
, makax++
kembalikan nomornya5
.dis.call(5)
, paksaan terhadap objek, saya tidak akan pernah menyangka itu.Ada dua cara berbeda untuk merepresentasikan angka:
Yang pertama adalah primitif, yang kedua adalah objek. Untuk semua maksud dan tujuan keduanya berperilaku sama, kecuali mereka terlihat berbeda ketika dicetak ke konsol. Satu perbedaan penting adalah bahwa, sebagai objek,
new Number(5)
menerima properti baru seperti halnya dataran{}
, sedangkan primitif5
tidak:Adapun bagian awal
dis.call(5)
, silakan lihat Bagaimana kata kunci "ini" berfungsi? . Anggap saja argumen pertamacall
yang digunakan sebagai nilaithis
, dan bahwa operasi ini memaksa angka ke dalamNumber
bentuk objek yang lebih kompleks . * Kemudian++
memaksa itu kembali ke bentuk primitif, karena operasi penambahan+
menghasilkan primitif baru.Sebuah
Number
objek menerima sifat baru.++
menghasilkan6
nilai primitif baru ...... yang tidak memiliki dan tidak menerima atribut khusus.
* Perhatikan bahwa dalam modus ketat yang
this
argumen akan diperlakukan berbeda dan akan tidak dikonversi keNumber
. Lihat http://es5.github.io/#x10.4.3 untuk detail implementasi.sumber
#define true false
. Atau di Jawa, di mana Anda bisa mendefinisikan kembali apa artinya angka. Ini adalah bahasa padat yang bagus. Sebenarnya, setiap bahasa memiliki "trik" serupa di mana Anda mendapatkan hasil yang berfungsi seperti yang dimaksudkan tetapi mungkin terlihat aneh.Ada Paksaan di Dunia JavaScript - Kisah Detektif
Nathan, Anda tidak tahu apa yang telah Anda temukan.
Saya sudah menyelidiki ini selama berminggu-minggu sekarang. Semuanya dimulai pada malam badai Oktober lalu. Saya tidak sengaja menemukan
Number
kelas - Maksud saya, mengapa di dunia ini JavaScript memilikiNumber
kelas?Saya tidak siap untuk apa yang akan saya cari tahu selanjutnya.
Ternyata JavaScript, tanpa memberi tahu Anda, telah mengubah angka Anda menjadi objek dan objek Anda menjadi angka tepat di bawah hidung Anda.
JavaScript berharap tidak ada yang akan menangkap, tetapi orang-orang telah melaporkan perilaku aneh yang tak terduga, dan sekarang terima kasih untuk Anda dan pertanyaan Anda. Saya punya bukti yang saya butuhkan untuk membuat hal ini terbuka lebar.
Inilah yang kami temukan sejauh ini. Saya tidak tahu apakah saya harus mengatakan ini kepada Anda - Anda mungkin ingin mematikan JavaScript Anda.
Ketika Anda membuat fungsi itu, Anda mungkin tidak tahu apa yang akan terjadi selanjutnya. Semuanya tampak baik-baik saja, dan semuanya baik-baik saja - untuk saat ini.
Tidak ada pesan kesalahan, hanya kata "tidak terdefinisi" dalam output konsol, persis apa yang Anda harapkan. Bagaimanapun, ini adalah deklarasi fungsi - tidak seharusnya mengembalikan apa pun.
Tapi ini baru permulaan. Apa yang terjadi selanjutnya, tidak ada yang bisa memprediksi.
Ya saya tahu, Anda mengharapkan
5
, tetapi bukan itu yang Anda dapatkan, apakah itu - Anda punya sesuatu yang lain - sesuatu yang berbeda.Hal yang sama terjadi pada saya.
Saya tidak tahu harus bagaimana. Itu membuatku gila. Saya tidak bisa tidur, saya tidak bisa makan, saya mencoba untuk meminumnya, tetapi Mountain Dew tidak akan membuat saya lupa. Itu tidak masuk akal!
Saat itulah saya mengetahui apa yang sebenarnya terjadi - itu adalah paksaan, dan itu terjadi tepat di depan mata saya, tetapi saya terlalu buta untuk melihatnya.
Mozilla mencoba menguburnya dengan meletakkannya di tempat yang mereka tahu tidak akan dilihat siapa pun - dokumentasi mereka .
Setelah berjam-jam membaca dan membaca kembali secara berulang dan membaca kembali, saya menemukan ini:
Itu ada di sana polos seperti yang bisa dibilang dalam font Open Sans. Itu
call()
fungsinya - bagaimana saya bisa sebodoh itu ?!Nomor saya sama sekali bukan angka. Saat saya menyebarkannya
call()
, itu menjadi sesuatu yang lain. Itu menjadi ... sebuah objek.Awalnya saya tidak percaya. Bagaimana ini bisa benar? Tetapi saya tidak bisa mengabaikan bukti yang meningkat di sekitar saya. Itu ada di sana jika Anda hanya melihat:
wtf
itu benar. Angka tidak dapat memiliki properti khusus - kita semua tahu itu! Ini hal pertama yang mereka ajarkan padamu di akademi.Kita seharusnya tahu saat kita melihat output konsol - ini bukan jumlah yang kami pikir itu. Ini adalah seorang penipu - sebuah benda yang lewat sebagai nomor manis kami yang tidak bersalah.
Ini adalah ...
new Number(5)
.Tentu saja! Itu masuk akal.
call()
punya pekerjaan untuk dilakukan, dia harus menjalankan fungsi, dan untuk itu dia perlu mengisithis
, dia tahu dia tidak bisa melakukan itu dengan angka - dia butuh objek dan dia bersedia melakukan apa pun untuk mendapatkannya, bahkan jika itu berarti memaksa nomor kita. Ketikacall()
melihat nomornya5
, dia melihat peluang.Itu adalah rencana yang sempurna: tunggu sampai tidak ada yang melihat dan menukar nomor kami dengan objek yang terlihat seperti itu. Kami mendapat nomor, fungsinya dipanggil, dan tidak ada yang lebih bijak.
Itu benar-benar rencana yang sempurna, tetapi seperti semua rencana, bahkan yang sempurna, ada lubang di dalamnya, dan kami akan jatuh ke dalamnya.
Lihat, yang
call()
tidak mengerti adalah bahwa dia bukan satu-satunya di kota yang bisa memaksa angka. Bagaimanapun, ini adalah JavaScript - paksaan ada di mana-mana.call()
mengambil nomor saya, dan saya tidak akan berhenti sampai saya menarik topeng dari penipu kecilnya dan mengekspos dia ke seluruh komunitas Stack Overflow.Tapi bagaimana caranya? Saya membutuhkan rencana. Tentu itu terlihat seperti angka, tetapi saya tahu tidak, pasti ada cara untuk membuktikannya. Itu dia! Itu terlihat seperti angka, tetapi bisakah itu bertindak seperti nomor?
Saya bilang
five
saya perlu dia menjadi 5 kali lebih besar - dia tidak bertanya mengapa dan saya tidak menjelaskan. Saya kemudian melakukan apa yang akan dilakukan oleh programmer yang baik: Saya mengalikannya. Tentunya tidak mungkin dia bisa menipu jalan keluar dari ini.Sial! Tidak hanya
five
multiply sajawtf
masih ada. Sialan orang ini dan kentangnya.Apa yang sedang terjadi? Apakah saya salah tentang semua ini? Apakah
five
benar-benar angka? Tidak, saya pasti kehilangan sesuatu, saya tahu itu, ada sesuatu yang harus saya lupakan, sesuatu yang sangat sederhana dan mendasar sehingga saya benar-benar mengabaikannya.Ini kelihatannya tidak bagus, saya telah menulis jawaban ini selama berjam-jam dan saya masih belum bisa menjelaskan maksud saya. Saya tidak dapat melanjutkan ini, akhirnya orang-orang akan berhenti membaca, saya harus memikirkan sesuatu dan saya harus memikirkannya dengan cepat.
Tunggu, itu saja!
five
bukan 25, 25 adalah hasilnya, 25 adalah angka yang sama sekali berbeda. Tentu saja, bagaimana saya bisa lupa? Angka tidak berubah. Ketika Anda melipatgandakan5 * 5
tidak ada yang ditugaskan untuk apa pun yang Anda buat nomor baru25
.Pasti itu yang terjadi di sini. Entah bagaimana ketika saya mengalikan
five * 5
,five
harus dipaksa menjadi angka dan angka itu harus menjadi nomor yang digunakan untuk perkalian. Ini hasil dari perkalian yang dicetak ke konsol, bukan nilaifive
itu sendiri.five
tidak pernah ditugaskan apa pun - jadi tentu saja itu tidak berubah.Jadi, bagaimana saya bisa
five
menetapkan sendiri hasil operasi. Saya mendapatkannya.five
Bahkan sebelum sempat berpikir, saya berteriak "++".Aha! Saya memilikinya! Semua orang yang tahu
5 + 1
adalah6
, ini adalah bukti yang saya butuhkan untuk mengekspos bahwafive
itu bukan angka! Itu penipu! Penipu buruk yang tidak tahu bagaimana cara menghitung. Dan saya bisa membuktikannya. Begini cara bilangan real bertindak:Tunggu? Apa yang sedang terjadi disini? desah aku begitu terjebak dalam penghancuran
five
sehingga aku lupa bagaimana operator pos bekerja. Ketika saya menggunakan++
di akhirfive
saya katakan kembalikan nilai saat ini, lalu kenaikanfive
. Ini nilai sebelum operasi terjadi yang akan dicetak ke konsol.num
sebenarnya6
dan saya bisa membuktikannya:Saatnya untuk melihat apa yang
five
sebenarnya:... persis seperti apa yang seharusnya.
five
bagus - tapi saya lebih baik. Jikafive
masih ada objek yang berarti masih memiliki propertiwtf
dan saya berani bertaruh semua yang tidak.Aha! Saya benar. Saya memilikinya!
five
dulu nomor - itu bukan obyek lagi. Saya tahu trik multiplikasi tidak akan menghemat waktu ini. Lihatfive++
benar-benarfive = five + 1
. Berbeda dengan perkalian,++
operator memberikan nilaifive
. Lebih khusus, ia memberikannya hasilfive + 1
yang sama seperti dalam kasus penggandaan mengembalikan angka abadi yang baru .Aku tahu aku memilikinya, dan hanya untuk memastikan dia tidak bisa keluar dari situ. Saya punya satu tes lagi di lengan baju saya. Jika saya benar, dan
five
benar-benar nomor sekarang, maka ini tidak akan berhasil:Dia tidak akan membodohiku saat ini. Saya tahu
potato?
akan dicetak ke konsol karena itu adalah hasil tugas. Pertanyaan sebenarnya adalah, apakahwtf
masih ada?Seperti yang saya duga - tidak ada - karena angka tidak dapat ditetapkan sebagai properti. Kami belajar bahwa tahun pertama di akademi;)
Nathan terima kasih. Terima kasih atas keberanian Anda mengajukan pertanyaan ini, akhirnya saya bisa melupakan semua ini dan beralih ke kasus baru.
Seperti ini tentang fungsinya
toValue()
. Ya Tuhan. Tidaaaak!sumber
01
mendeklarasikan fungsidis
yang mengembalikan objek konteks. Apa yangthis
mewakili perubahan tergantung pada apakah Anda menggunakan mode ketat atau tidak. Seluruh contoh memiliki hasil yang berbeda jika fungsi tersebut dinyatakan sebagai:Ini dirinci dalam bagian 10.4.3 dalam spesifikasi ES5
02
adalah nilai pengembalian dari deklarasi fungsi.undefined
harus jelas di sini.03
variabelfive
diinisialisasi dengan nilai pengembaliandis
ketika dipanggil dalam konteks nilai primitif5
. Karenadis
tidak dalam mode ketat, saluran ini identik dengan panggilanfive = Object(5)
.04
NilaiNumber {[[PrimitiveValue]]: 5}
balik ganjil adalah representasi objek yang membungkus nilai primitif5
05
yangfive
objekwtf
properti ditugaskan nilai string'potato'
06
adalah nilai pengembalian tugas dan harus jelas.07
yangfive
objekwtf
properti sedang diperiksa08
sepertifive.wtf
yang sebelumnya diatur untuk'potato'
kembali ke'potato'
sini09
yangfive
objek sedang dikalikan dengan nilai primitif5
. Ini tidak berbeda dengan objek lain yang dikalikan dan dijelaskan di bagian 11.5 dari spesifikasi ES5 . Dari catatan khusus adalah bagaimana benda dilemparkan ke nilai numerik, yang dibahas dalam beberapa bagian.9.3 ToNumber :
9.1 ToPrimitive :
8.12.8 [[Nilai Default]] :
Ini semua adalah cara bundaran untuk mengatakan bahwa
valueOf
fungsi objek dipanggil dan nilai pengembalian dari fungsi tersebut digunakan dalam persamaan. Jika Anda ingin mengubahvalueOf
fungsi, Anda dapat mengubah hasil operasi:10
karena fungsifive
svalueOf
tidak berubah, ia mengembalikan nilai primitif yang dibungkus5
sehinggafive * 5
mengevaluasi5 * 5
yang menghasilkan25
11
yangfive
objekwtf
properti dievaluasi lagi meskipun telah berubah dari ketika ditugaskan pada05
.12
'potato'
13
yang Postfix Kenaikan Operator disebut padafive
, yang mendapat nilai numerik (5
, kita bahas bagaimana sebelumnya), toko nilai sehingga dapat dikembalikan, menambahkan1
untuk nilai (6
), memberikan nilai untukfive
, dan kembali nilai yang disimpan (5
)14
seperti sebelumnya, nilai yang dikembalikan adalah nilai sebelum ditambahkan15
yangwtf
properti dari nilai primitif (6
) disimpan di variabelfive
diakses. Bagian 15.7.5 dari spesifikasi ES5 mendefinisikan perilaku ini. Angka mendapatkan properti dariNumber.prototype
.16
Number.prototype
tidak memilikiwtf
properti, jadiundefined
dikembalikan17
five.wtf
diberi nilai'potato?'
. Penugasan didefinisikan dalam 11.13.1 dari spesifikasi ES5 . Pada dasarnya nilai yang diberikan dikembalikan tetapi tidak disimpan.18
'potato?'
dikembalikan oleh operator penugasan19
lagifive
, yang memiliki nilai6
diakses, dan sekali lagiNumber.prototype
tidak memilikiwtf
properti20
undefined
seperti yang dijelaskan di atas21
five
diakses22
6
dikembalikan seperti yang dijelaskan dalam13
sumber
Sederhana saja.
Ini mengembalikan
this
konteksnya. Jadi, jika Anda melakukannyacall(5)
Anda melewati angka sebagai objek.The
call
fungsi tidak menyediakan argumen, argumen pertama yang Anda berikan adalah konteksthis
. Biasanya jika Anda ingin pada itu pada konteks, Anda memberikan{}
begitudis.call({})
, yang berartithis
dalam fungsi adalah kosongthis
. Namun, jika Anda lulus5
sepertinya akan dikonversi ke objek. Lihat .callJadi kembalinya adalah
object
Ketika Anda melakukannya
five * 5
, JavaScript melihat objekfive
sebagai tipe primitif, sehingga setara dengan5 * 5
. Menariknya, lakukan'5' * 5
, masih sama25
, jadi JavaScript jelas casting di bawah tenda. Tidak ada perubahan pada yang mendasarinyafive
tipe yang dilakukan pada baris iniTetapi ketika Anda melakukannya
++
akan mengkonversi objek kenumber
tipe primitif sehingga menghapus.wtf
properti. Karena Anda memengaruhi tipe yang mendasarinyasumber
++
mengonversi dan menetapkannya kembali.++
sama denganvariable = variable + 1
. Jadi, Anda kehilanganwtf
*
vs++
tidak membingungkan saya sama sekali. Memiliki fungsi yang tidak mengharapkan argumen dan mengembalikanthis
, tetap memiliki fungsi tersebut menerima argumen dan mengembalikan sesuatu yang seperti, tetapi tidak tepat, argumen - yang tidak masuk akal bagi saya.dis.call()
dilakukannya.this
hanyalah sebuah pointer ke objek sehingga tipe primitif dikonversi secara implisit. Mengapa fungsi tanpa argumen tidak dapat memiliki setidaknya konteks? Argumen pertamacall
ataubind
digunakan untuk mengatur konteks. Juga, fungsi adalah penutupan yang berarti mereka memiliki akses ke lebih dari sekadararguments
Nilai-nilai primitif tidak dapat memiliki properti. Tetapi ketika Anda mencoba untuk mengakses ke properti pada nilai primitif, itu transparan transstype ke objek Nomor sementara.
Begitu:
sumber
Deklarasikan fungsi
dis
. Fungsi mengembalikan konteksnyaPanggil
dis
dengan konteks5
. Nilai-nilai primitif dikotak bila diteruskan sebagai konteks dalam mode ketat ( MDN ). Jadifive
sekarang adalah objek (nomor kotak).Nyatakan
wtf
properti padafive
variabelNilai dari
five.wtf
five
kotak5
, jadi itu nomor dan objek pada saat yang sama (5 * 5 = 25). Itu tidak berubahfive
.Nilai dari
five.wtf
Buka kotak di
five
sini.five
sekarang hanya primitifnumber
. Mencetak5
, dan kemudian menambahkan1
kefive
.five
adalah bilangan primitif6
sekarang, tidak ada properti di dalamnya.primitif tidak dapat memiliki properti, Anda tidak dapat mengatur ini
Anda tidak dapat membaca ini, karena belum disetel
five
adalah6
karena pasca incrementing atassumber
Pertama sepertinya ini sedang dijalankan melalui konsol nodejs.
1.
menciptakan fungsi dis (), tetapi karena itu tidak ditetapkan sebagai
var
tidak ada nilai untuk kembali begituundefined
juga output, meskipundis()
didefinisikan. Pada sidenote,this
tidak dikembalikan karena fungsinya tidak dijalankan.2.
Pengembalian ini javascript ini
Number
objek karena Anda hanya mengatur fungsidis()
'sthis
nilai primitif lima.3.
Pengembalian pertama
"potato"
karena Anda hanya mengatur propertiwtf
darifive
ke'potato'
. Javascript mengembalikan nilai variabel yang Anda atur, membuatnya mudah untuk mem-rantai berbagai variabel dan mengaturnya ke nilai yang sama seperti ini:a = b = c = 2
.4.
Ini kembali
25
karena Anda baru saja mengalikan angka primitif5
kefive
. Nilaifive
ditentukan oleh nilaiNumber
objek.5.
Saya melewatkan baris ini sebelumnya karena saya akan mengulanginya di sini. Itu hanya mengembalikan nilai properti
wtf
yang Anda tetapkan di atas.6.
Seperti yang dikatakan @Callum,
++
akan mengkonversi tipe kenumber
dari nilai yang sama dari objekNumber {[[PrimitiveValue]]: 5}}
.Sekarang karena
five
anumber
, Anda tidak dapat mengatur properti lagi sampai Anda melakukan sesuatu seperti ini:atau
Perhatikan juga bahwa cara kedua akan memiliki perilaku yang berbeda daripada menggunakan metode pertama karena itu mendefinisikan objek generik daripada
Number
objek yang dibuat sebelumnya.Saya harap ini membantu, javascript suka mengasumsikan sesuatu, sehingga bisa membingungkan ketika mengubah dari
Number
objek ke primitifnumber
. Anda dapat memeriksa apa jenis sesuatu dengan menggunakantypeof
kata kunci, menulis jenis lima setelah Anda menginisialisasi itu kembali'object'
, dan setelah Anda melakukannyafive++
kembali'number'
.@deceze menjelaskan perbedaan antara objek Number dan primitive number dengan sangat baik.
sumber
Lingkup JavaScript dibuat dari Konteks Eksekusi. Setiap Konteks Eksekusi memiliki Lingkungan Leksikal (nilai eksternal / cakupan global), Lingkungan Variabel (nilai cakupan lokal), dan ini mengikat .
The mengikat ini adalah bagian yang sangat penting dari Konteks Eksekusi. Menggunakan
call
adalah salah satu cara untuk mengubah pengikatan ini , dan dengan begitu akan secara otomatis membuat objek untuk mengisi pengikatan.Function.prototype.call () (dari MDN)
Setelah terbukti bahwa 5 diubah menjadi
new Number(5)
, sisanya harus agak jelas. Perhatikan bahwa contoh lain juga akan berfungsi selama mereka adalah nilai primitif.sumber
Beberapa konsep menjelaskan apa yang terjadi
5
adalah angka, nilai primitifNumber {[[PrimitiveValue]]: 5}
adalah turunan dari Number (sebut saja objek wrapper)Setiap kali Anda mengakses properti / metode pada nilai primitif, mesin JS akan membuat pembungkus objek dari tipe yang sesuai (
Number
untuk5
,String
untuk'str'
danBoolean
untuktrue
) dan menyelesaikan panggilan akses / metode properti pada pembungkus objek tersebut. Inilah yang terjadi ketika Anda melakukannyatrue.toString()
misalnya.Saat melakukan operasi pada objek, mereka dikonversi ke nilai primitif (dengan menggunakan
toString
atauvalueOf
) untuk menyelesaikan operasi tersebut - misalnya saat melakukanstring
akan memegang rangkaian string darimystr
danobj.toString()
dannumber
akan menahan penambahan3
danobj.valueOf()
.Sekarang untuk menyatukan semuanya
dis.call(5)
berperilaku seperti(5).dis()
jika5
benar-benar punya metodedis
. Untuk menyelesaikan pemanggilan metode, pembungkus objek dibuat dan pemanggilan metode diselesaikan. Pada titik ini lima poin ke pembungkus objek di sekitar nilai primitif 5.Menetapkan properti pada objek, tidak ada yang mewah di sini.
Ini sebenarnya
five.valueOf() * 5
mendapatkan nilai primitif dari objek wrapper.five
masih menunjuk ke objek awal.Ini sebenarnya
five = five.valueOf() + 1
. Sebelum baris inifive
memegang pembungkus objek di sekitar nilai 5, sedangkan setelah titik inifive
memegang nilai primitif6
.five
bukan lagi obyek. Masing-masing baris menciptakan instance Nomor baru untuk menyelesaikan.wtf
akses properti. Mesin virtual independen, jadi menyetel properti pada satu tidak akan terlihat pada yang lain. Kode ini sepenuhnya sama dengan yang ini:sumber