Apa sebenarnya Type Coercion di Javascript?

122

Apa sebenarnya pemaksaan tipe di Javascript?

Misalnya, tentang penggunaan, ==bukan ===?

gespinha
sumber
21
(true == 1) => true/ (true === 1) => false.
VisioN
5
@VisioN komentar Anda tidak membantu sama sekali, saya bertanya: "mengapa" hal itu terjadi?
gespinha
3
Itu terjadi karena JavaScript dikembangkan dengan cara ini. Komentar saya harus menjawab pertanyaan utama Anda: Apa sebenarnya Type Coercion di Javascript?
VisioN
6
Melalui YDJS: "Mengonversi nilai dari satu jenis ke jenis lainnya sering disebut" pemilihan jenis ", jika dilakukan secara eksplisit, dan" pemaksaan "bila dilakukan secara implisit (dipaksa oleh aturan tentang bagaimana nilai digunakan)." - github.com/getify/You-Dont-Know-JS/blob/master/…
mattLummus

Jawaban:

177

Jenis koersi berarti bahwa ketika operan dari sebuah operator adalah tipe yang berbeda, salah satunya akan diubah menjadi nilai "ekuivalen" dari tipe operan lainnya. Misalnya, jika Anda melakukan:

boolean == integer

operan boolean akan diubah menjadi integer: falsemenjadi 0, truemenjadi 1. Kemudian kedua nilai tersebut dibandingkan.

Namun, jika Anda menggunakan operator perbandingan non-konversi ===, tidak ada konversi yang terjadi. Jika operan memiliki tipe yang berbeda, operator ini akan kembali false, dan hanya membandingkan nilai jika berjenis sama.

Barmar
sumber
1
Bagaimana saya bisa meletakkan ini dalam situasi praktis? Bukankah saya harus selalu menggunakan ===ketika saya ingin membandingkan jika suatu nilai sama dengan yang lain?
gespinha
1
Itu tergantung pada apa yang Anda lakukan. Lihat pertanyaan terkait.
Barmar
8
@GEspinha yah itulah "seni" menggunakan bahasa yang diketik secara longgar. Beberapa orang berpikir demikian, dan secara umum berpikir bahasa yang diketik longgar adalah momok dunia pemrograman. Namun, jika Anda tahu apa yang Anda lakukan, itu dapat membuat kode yang lebih pendek dan lebih fleksibel.
Crayon Violent
2
@Barmar Apakah itu juga berlaku untuk > , <?
Royi Namir
2
Referensi dan penjelasan yang sangat baik tentang pemaksaan: github.com/getify/You-Dont-Know-JS/blob/master/…
Greg Bell
56

Mari kita mulai dengan pengenalan singkat tentang sistem tipe yang menurut saya akan membantu Anda memahami gagasan umum tentang pemaksaan tipe.

Sistem tipe dari suatu bahasa mendefinisikan aturan yang memberi tahu kita tipe data apa yang ada dalam bahasa itu dan bagaimana mereka dapat digabungkan menggunakan operator yang berbeda. Misalnya, salah satu aturan tersebut mungkin menetapkan bahwa operator plus (+) hanya bekerja pada angka. Aturan-aturan ini ada terutama untuk mencegah Anda menembak diri sendiri di kaki. Tapi apa yang terjadi jika programmer melanggar aturan itu dalam program? Tidak ada yang mencegah programmer untuk mengetik {} + {}atau “hello” + 5dalam sebuah program meskipun bahasanya tidak menganggap ekspresi itu masuk akal.

Apa yang akhirnya terjadi dalam situasi tersebut bergantung pada seberapa ketat bahasa tersebut tentang aturan jenisnya.

Sistem tipe bahasa sering kali memegang salah satu dari dua posisi tentang Anda yang melanggar aturannya:

  1. Katakan "Hei, itu tidak keren!" dan segera hancurkan program Anda.
  2. Katakan “Saya tidak bisa melakukan apa pun dengan {}… tapi saya bisa melakukan sesuatu dengan angka” dan coba ubah {} menjadi angka.

Bahasa dengan sistem jenis yang menempati posisi pertama tentang aturannya dalam bahasa sehari-hari disebut sebagai bahasa yang "diketik dengan kuat". Mereka tegas tentang tidak membiarkan Anda melanggar aturannya. Bahasa yang mengambil pendekatan kedua (seperti JavaScript) disebut sebagai bahasa yang "diketik lemah" atau "diketik longgar". Tentu, Anda dapat melanggar aturan, tetapi jangan kaget ketika itu mengubah jenis data yang Anda jelaskan dalam program Anda secara paksa untuk mematuhi aturannya. Perilaku itu dikenal sebagai… (drum roll)… paksaan tipe .

Sekarang mari kita lihat beberapa contoh di JavaScript. Pertama, mari kita mulai dengan ekspresi yang tidak mengarah pada pemaksaan tipe.

5 + 5

Menggunakan operator + dengan dua angka yang benar-benar valid. Program akan memperlakukan + sebagai “tambah” dan dengan senang hati menambahkan kedua angka tersebut. Tidak perlu konversi.

Tapi bagaimana dengan…

[] + 5

Uh oh. Dalam JavaScript, +bisa berarti menambahkan dua angka atau menggabungkan dua string. Dalam hal ini, kami tidak memiliki dua angka atau dua string. Kami hanya memiliki satu nomor dan satu objek. Menurut aturan tipe JavaScript, ini tidak masuk akal. Karena itu memaafkan tentang Anda yang melanggar aturannya, alih-alih menabraknya, ia mencoba memahaminya. Jadi, apa yang dilakukan JavaScript? Yah, ia tahu bagaimana menggabungkan string, jadi ia mengubah [] dan 5 menjadi string dan hasilnya adalah nilai string "5".

Apa masalahnya dengan operator perbandingan ==dan ===? Mengapa ada dua operator pembanding?

==tidak kebal terhadap perilaku konversi jenis JavaScript. Ekspresi seperti 5 == “5”akan dievaluasi menjadi true karena JavaScript akan mencoba mengonversi salah satunya sehingga membandingkan jenis data yang sama.

Dalam banyak kasus, hal itu tidak diinginkan karena Anda mungkin ingin tahu apakah beberapa data yang Anda bandingkan memiliki jenis yang berbeda sehingga Anda dapat memutuskan apa yang harus dilakukan. Di situlah ===operator masuk. Saat Anda menggunakan ===, tidak ada jenis konversi yang akan terjadi. Oleh karena itu, ekspresi 5 === “5”akan dievaluasi sebagai salah.

linstantnoodles
sumber
4
terima kasih atas penjelasan yang bagus, terutama untuk "Sistem tipe bahasa sering menempati salah satu dari dua posisi"
Humoyun Ahmad
1
Ini harus menjadi jawaban yang diterima, karena ini menunjukkan pemaksaan tipe otomatis dalam berbagai aspek, bukan hanya contoh perbandingan ==. Jawaban ini melakukan pekerjaan yang jauh lebih baik dalam menjawab pertanyaan dan menghilangkan semua ambiguitas. Terima kasih telah meluangkan waktu untuk menuliskannya.
chad
6

Di Python jika Anda mencoba menambahkan, katakanlah, string dan integer, Anda mendapatkan error:

>>> "hi" + 10
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects

Namun di JavaScript, Anda tidak melakukannya. Itu 10akan diubah menjadi string:

> "hi" + 10
"hi10"

"Type coercion" adalah istilah yang salah untuk di atas. Pada kenyataannya, tidak ada bahasa yang memiliki "tipe" dalam pengertian Java atau C atau bahasa lain dengan sistem tipe statis. Bagaimana bahasa memperlakukan interaksi antara berbagai nilai yang diketik secara non-statis adalah masalah pilihan dan konvensi.

Claudiu
sumber
1
Saya pikir ada sedikit masalah dengan contoh yang Anda ambil. Apa yang Anda sarankan sebagai contoh untuk JS, bekerja sempurna dengan Java dan C #. Jadi, menurut jawaban ini, jika seseorang menyimpulkan bahwa pemaksaan tipe dukungan Java dan C # itu tidak sepenuhnya benar ...
Romeo Sierra
3

izinkan saya menjelaskan pemaksaan tipe dengan contoh berikut

Type Coercion berarti Javascript secara otomatis (on-the-fly) mengubah variabel dari satu tipe data ke tipe data lainnya

Contoh: 123 + "4"umumnya menimbulkan kesalahan tetapi di Javascript karena pemaksaan tipe, itu menghasilkan 1234string

if(23 == "23"){
    console.log(" this line is inside the loop and is executed ");
}

Pada kode di atas, karena pemaksaan tipe - JavaScript menganggap 23(angka) dan "23"(string) adalah hal yang sama. ini membuat kondisi menjadi benar dan mencetak console.log

Dalam kasus lain

if(23 === "23"){
   console.log(" this line is inside the loop and is NOT executed");
}

Dalam ===kasus Javascript tidak melakukan Type Coercion, dan karena 23adalah angka dan "23"String dan karena ===kedua tipe data ini berbeda dan itu mengarah ke false. Itu tidak mencetak console.log

Dengan kata sederhana

Dalam hal =ini adalah operator penugasan - yang memberikan nilai sepertivar a = 3; , dll

(di bawah ini operator untuk perbandingan)

Dalam hal ini ==Javascript mengubah / memaksa tipe data ke yang lain dan kemudian membandingkannya.

Dalam hal ini === Javascript tidak mengubah / memaksa tipe data

Untuk menghindari bug dan untuk tujuan debugging === banyak digunakan

Tolong beri tahu saya keakuratan informasi di atas.

PRagh
sumber
2

Apa itu paksaan:

Jenis paksaan dalam javascript terjadi ketika mesin Javascript harus melakukan operasi tertentu yang membutuhkan datanya dalam jenis tertentu. Ketika mesin menemukan data dalam tipe tertentu yang tidak berlaku untuk operasi itu kemudian memaksa data menjadi tipe tertentu. Ini diperlukan karena variabel dalam javascript diketik secara dinamis, yang berarti bahwa variabel tertentu dapat diberi nilai jenis apa pun.

Contoh:


if(1){
  // 1 gets coerced to true
}


if(4 > '3') {
  // 3 gets coerced into a number
}


44 == "44"  // true, the string 44 gets converted to a nr

Paksaan Boolean:

Dalam paksaan javascript, semua nilai diubah menjadi truekecuali untuk nilai-nilai berikut yang dipaksakan menjadi false:

console.log(!!"");         // false
console.log(!!0);          // false
console.log(!!null);       // false
console.log(!!undefined);  // false
console.log(!!NaN);        // false
console.log(!!false);      // false

Perhatikan juga bahwa dalam contoh di atas bahwa double! operator digunakan. The! operator mark memaksa nilai menjadi boolean dengan nilai yang berlawanan. Kita bisa menggunakan operator ini dua kali untuk mengubah nilai apapun menjadi boolean.

Willem van der Veen
sumber
1

a == bberarti javascript akan mengevaluasi amelawan bberdasarkan jika nilai-nilai dapat dievaluasi sama. Misalnya, false == 0akan dievaluasi sebagai benar karena 0 juga merupakan nilai dari Boolean salah. Namun, false === 0akan dievaluasi salah karena membandingkan secara ketat, 0 bukanlah nilai fisik yang sama dengan salah. Contoh lain adalah false == ''Jadi pada dasarnya perbandingan longgar vs. perbandingan ketat, karena javascript adalah bahasa yang diketik secara longgar. Artinya, javascript akan mencoba untuk mengubah variabel berdasarkan konteks kode, dan ini memiliki efek membuat semuanya sama jika tidak dibandingkan secara ketat. php juga memiliki perilaku ini.

Crayon Violent
sumber
0 is not the same physical value as false. IMO secara fisik falsepersis 0di memori. Saya lebih suka mengatakan mereka berbeda menurut jenisnya, karena falseboolean, sedangkan 0integer.
VisioN
1

Jenis koersi adalah proses mengubah nilai dari satu jenis ke jenis lainnya (seperti string ke angka, objek ke boolean, dan sebagainya). Tipe apa pun, baik itu primitif atau objek, adalah subjek yang valid untuk pemaksaan tipe. Untuk diingat, primitifnya adalah: number, string, boolean, null, undefined + Symbol (ditambahkan di ES6).

Pemaksaan implisit vs. eksplisit Jenis pemaksaan bisa eksplisit dan implisit.

Saat pengembang mengungkapkan niat untuk mengonversi antar jenis dengan menulis kode yang sesuai, seperti Number(value) , itu disebut pemaksaan tipe eksplisit (atau tipe casting).

Karena JavaScript adalah bahasa yang diketik lemah, nilai juga dapat dikonversi di antara jenis yang berbeda secara otomatis, dan ini disebut paksaan jenis implisit. Ini biasanya terjadi ketika Anda menerapkan operator untuk nilai-nilai dari berbagai jenis, seperti 1 == null, 2/’5', null + new Date(), atau dapat dipicu oleh konteks sekitarnya, seperti dengan if (value) {…}, di mana nilai yang dipaksa untuk boolean.

Salah satu operator yang tidak memicu pemaksaan tipe implisit adalah ===, yang disebut operator kesetaraan ketat. Operator kesetaraan longgar ==di sisi lain melakukan perbandingan dan pemaksaan tipe jika diperlukan.

Paksaan tipe implisit adalah pedang bermata dua: ini adalah sumber frustrasi dan cacat yang hebat, tetapi juga mekanisme yang berguna yang memungkinkan kita menulis lebih sedikit kode tanpa kehilangan keterbacaan.

Tiga jenis konversi Aturan pertama yang harus diketahui adalah hanya ada tiga jenis konversi di JavaScript:

  • untuk merangkai
  • ke boolean
  • ke nomor

Kedua, logika konversi untuk primitif dan objek bekerja secara berbeda, tetapi primitif dan objek hanya dapat dikonversi dengan tiga cara tersebut.

Mari kita mulai dengan primitif dulu.

Konversi string

Untuk secara eksplisit mengonversi nilai menjadi string, terapkan fungsi String (). Paksaan implisit dipicu oleh operator + biner, jika operan apa pun adalah string:

String(123) // explicit
123 + ''    // implicit

Semua nilai primitif diubah menjadi string secara alami seperti yang Anda harapkan:

String(123)                   // '123'
String(-12.3)                 // '-12.3'
String(null)                  // 'null'
String(undefined)             // 'undefined'
String(true)                  // 'true'
String(false)                 // 'false'

Konversi simbol agak rumit, karena hanya dapat diubah secara eksplisit, tetapi tidak secara implisit.

String(Symbol('my symbol'))   // 'Symbol(my symbol)'
'' + Symbol('my symbol')      // TypeError is thrown

Konversi Boolean

Untuk secara eksplisit mengonversi nilai menjadi boolean, terapkan Boolean()fungsinya. Konversi implisit terjadi dalam konteks logika, atau dipicu oleh operator logika ( || && !).

Boolean(2)          // explicit
if (2) { ... }      // implicit due to logical context
!!2                 // implicit due to logical operator
2 || 'hello'        // implicit due to logical operator

Catatan: Operator logika seperti || and &&melakukan konversi boolean secara internal, tetapi sebenarnya mengembalikan nilai operan asli, meskipun bukan boolean.

// returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123;   // x === 123

Segera setelah hanya ada 2 kemungkinan hasil konversi boolean: benar atau salah, akan lebih mudah mengingat daftar nilai palsu.

Boolean('')           // false
Boolean(0)            // false     
Boolean(-0)           // false
Boolean(NaN)          // false
Boolean(null)         // false
Boolean(undefined)    // false
Boolean(false)        // false

Nilai apa pun yang tidak ada dalam daftar akan dikonversi true, termasuk object,function , Array, Date, jenis yang ditetapkan pengguna, dan sebagainya. Simbol adalah nilai kebenaran. Objek kosong dan array juga merupakan nilai kebenaran:

Boolean({})             // true
Boolean([])             // true
Boolean(Symbol())       // true
!!Symbol()              // true
Boolean(function() {})  // true

Konversi numerik

Untuk konversi eksplisit, cukup terapkan Number() fungsinya, sama seperti yang Anda lakukan dengan Boolean()dan String().

Konversi implisit itu rumit, karena dipicu di lebih banyak kasus:

  • operator perbandingan (>, <, <=,> =)

  • operator bitwise (| & ^ ~)

  • operator aritmatika (- + * /%). Perhatikan, bahwa biner + tidak memicu konversi numerik, jika operan apa pun adalah string.

  • operator + unary

  • operator persamaan longgar == (termasuk! =).

    Perhatikan bahwa == tidak memicu konversi numerik jika kedua operan adalah string.

    Bilangan ('123') // eksplisit + '123' // implisit 123! = '456' // implisit 4> '5' // implisit 5 / null // implisit benar | 0 // implisit

Berikut adalah bagaimana nilai primitif diubah menjadi angka:

Number(null)                   // 0
Number(undefined)              // NaN
Number(true)                   // 1
Number(false)                  // 0
Number(" 12 ")                 // 12
Number("-12.34")               // -12.34
Number("\n")                   // 0
Number(" 12s ")                // NaN
Number(123)                    // 123
Tejas Savaliya
sumber
0
var str = 'dude';
console.log(typeof str); // "string"
console.log(!str); // false
console.log(typeof !str); // "boolean"

Contoh variabel yang awalnya dideklarasikan sebagai string yang dipaksa menjadi nilai boolean dengan! operator

Tuan P
sumber
3
Tolong uraikan jawaban Anda. Jawaban kode saja tidak terlalu membantu.
cezar
3
secara pribadi saya menemukan contoh kode hanya ringkas, cukup jelas dan sangat berguna, saya kira ini adalah masalah pendapat pribadi
Tuan P
0

Jenis koersi adalah proses mengubah nilai dari satu jenis ke jenis lainnya (seperti string ke angka, objek ke boolean, dan sebagainya). Tipe apa pun, baik itu primitif atau objek, adalah subjek yang valid untuk pemaksaan tipe. Untuk diingat, primitifnya adalah: number, string, boolean, null, undefined + Symbol (ditambahkan di ES6).

Jenis paksaan bisa eksplisit dan implisit.

Ketika pengembang mengungkapkan niat untuk mengonversi antar jenis dengan menulis kode yang sesuai, seperti Angka (nilai), itu disebut pemaksaan tipe eksplisit (atau tipe casting).

Karena JavaScript adalah bahasa yang diketik lemah, nilai juga dapat dikonversi di antara jenis yang berbeda secara otomatis, dan ini disebut paksaan jenis implisit. Ini biasanya terjadi ketika Anda menerapkan operator ke nilai dari jenis yang berbeda, seperti 1 == null, 2 / '5', null + new Date (), atau dapat dipicu oleh konteks sekitarnya, seperti dengan if (value) {… }, di mana nilai dipaksa menjadi boolean.

berikut adalah beberapa contoh pemaksaan tipe implisit:

true + false
12 / "6"
"number" + 15 + 3
15 + 3 + "number"
[1] > null
"foo" + + "bar"
'true' == true
false == 'false'
null == ''
!!"false" == !!"true"
[‘x’] == x
[] + null + 1
[1,2,3] == [1,2,3]
{}+[]+{}+[1]
!+[]+[]+![]
new Date(0) - 0
new Date(0) + 0

baca lebih lanjut: https://www.freecodecamp.org/news/js-type-coercion-explained-27ba3d9a2839/

Mahdi Salehian
sumber
-2

Jika tipe data tidak sama satu sama lain maka Terjadi Pemaksaan. seperti 3 == "3" atau boolen == integer

ASAbir
sumber