JSLint Diharapkan '===' dan sebagai gantinya melihat '=='

90

Baru-baru ini saya menjalankan beberapa kode saya melalui JSLint ketika saya menemukan kesalahan ini. Hal yang menurut saya lucu tentang kesalahan ini adalah bahwa kesalahan ini secara otomatis mengasumsikan bahwa semua == harus ===.

Apakah itu masuk akal? Saya dapat melihat banyak contoh yang tidak ingin Anda bandingkan jenisnya, dan saya khawatir ini benar-benar dapat menyebabkan masalah.

Kata "Diharapkan" akan menyiratkan bahwa ini harus dilakukan SETIAP waktu ..... Itulah yang tidak masuk akal bagi saya.

Metropolis
sumber
7
Saya mengalami ini juga dengan JSLint. Saya membuat pembaruan dari == menjadi === dan itu benar-benar merusak kode yang sebelumnya berfungsi.
kemiller2002
5
Jika kode Anda memiliki lebih dari 100 baris, itu tidak akan melewati jslint, sungguh, itu tidak mungkin.
3
"Broke" adalah kata yang terlalu kuat. Itu mengubah arti kode Anda. Jika Anda melakukan myVar == nullpemeriksaan, ya, perubahan besar. ; ^) Argumen Crockford adalah bahwa itu membuat makna kode lebih tepat, dan itu sulit untuk diperdebatkan.
ruffin

Jawaban:

127

IMO, menggunakan secara membabi buta ===, tanpa mencoba memahami cara kerja konversi jenis tidak masuk akal.

Ketakutan utama tentang operator Equals ==adalah bahwa aturan perbandingan yang bergantung pada jenis yang dibandingkan dapat membuat operator menjadi non-transitif, misalnya, jika:

A == B AND
B == C

Tidak benar-benar menjamin bahwa:

A == C

Sebagai contoh:

'0' == 0;   // true
 0  == '';  // true
'0' == '';  // false

Operator Strict Equals ===tidak terlalu diperlukan saat Anda membandingkan nilai dengan tipe yang sama, contoh paling umum:

if (typeof foo == "function") {
  //..
}

Kami membandingkan hasil typeofoperator, yang selalu berupa string , dengan string literal ...

Atau ketika Anda mengetahui aturan pemaksaan tipe, misalnya, periksa apakah ada sesuatu nullatau undefinedsesuatu:

if (foo == null) {
  // foo is null or undefined
}

// Vs. the following non-sense version:

if (foo === null || typeof foo === "undefined") {
  // foo is null or undefined
}
Christian C. Salvadó
sumber
1
Saya benci aturan JSLint ini. Menurut saya masalah sebenarnya adalah orang tidak boleh menggunakan operator dengan cara yang tidak mereka pahami (ironisnya, mereka adalah jenis orang yang sama yang secara membabi buta mengganti '===' dengan '=='). Tentu, ada beberapa kasus biasa yang muncul saat membandingkan angka 0 dengan berbagai string, tetapi jika Anda membandingkan data yang tidak terkait seperti 0 == 'ini adalah string' - Kode Anda mungkin memiliki masalah yang lebih besar daripada dua kali lipat! Jika Anda tahu pasti jenis apa yang Anda hadapi dan Anda tahu persis bagaimana mereka berinteraksi dengan ==, maka saya pikir Anda harus menggunakannya.
Jon
3
@Jon Inti dari ===operator adalah kejelasan kode. Tidak ada situasi yang masuk akal untuk digunakan ==karena tidak akan pernah sejelas dan dapat dipahami sebagai operator identitas. Ini bukan tentang apakah Anda memahami operator atau tidak, ini tentang penggunaan yang membuat kode Anda lebih mudah dibaca dengan hampir tanpa biaya. Satu-satunya pengembang yang menentang operator identitas adalah pengembang tunggal dan orang-orang yang tidak bekerja dalam tim. Menurut definisi, orang yang kodenya tidak ditinjau oleh cukup banyak mata.
Alternatex
2
Saya menemukan perbandingan == nol menjadi hampir penting. Masalah menjadi kurang penting jika kode Anda diuji dengan baik.
Jon
1
Sebenarnya ada saat-saat ketika menggunakan == sangat penting, untuk melakukan tes yang diperlukan. jika foo.toString () akan tampil dengan cara yang dapat diprediksi dan string biasa perlu diuji terhadap keluaran tersebut, maka menulis foo == stringToTest jauh lebih bersih daripada foo.toString () === stringToTest.
Crispen Smith
2
@Alternatex Jika intinya adalah kejelasan, mereka seharusnya tidak membuatnya TRIPLE sama! Tidak ada pemula yang memahaminya. Setidaknya dua kali sama diketahui dari bahasa lain. Juga, there is no reasonable situationadalah salah saji yang parah. Pikirkan tentang jenis Javascript (asli) Numberdan String. Keberadaan mereka membuktikan bahwa penulis Javascript memiliki kasus penggunaan tertentu dalam pikirannya ==. Apakah menurut Anda new String('hi') === 'hi'penilaian ke falsesangat jelas? Harap tulis potongan kode yang menguji argumen fungsi Anda agar tidak 'hi'menerima String dan string dan beri tahu saya bahwa itu sudah jelas.
Stijn de Witt
25

JSLint secara inheren lebih defensif daripada yang dimungkinkan oleh sintaks Javascript.

Dari dokumentasi JSLint:

The ==dan !=operator melakukan jenis paksaan sebelum membandingkan. Ini buruk karena menyebabkan ' \t\r\n' == 0menjadi kenyataan. Ini dapat menutupi kesalahan jenis.

Saat membandingkan dengan salah satu nilai berikut, gunakan operator ===or !==(yang tidak melakukan paksaan ketik):0 '' undefined null false true

Jika Anda hanya peduli bahwa nilai yang truthy atau falsy , kemudian menggunakan bentuk pendek. Dari pada

(foo != 0)

hanya mengatakan

(foo)

dan bukannya

(foo == 0)

mengatakan

(!foo)

The ===dan !==operator lebih disukai.

Daniel Vandersluis
sumber
8
Saya harus menyimpulkan bahwa orang-orang dari JSLint bekerja di menara gading yang sangat tinggi sehingga mereka tidak pernah keluar. Javascript dirancang untuk digunakan dengan ==operator. The ===adalah kasus khusus ... JSLint mencoba untuk membuatnya tampak seperti menggunakan ==entah bagaimana salah ... Namun, cobalah ini: var x = 4, y = new Number(4); if (x == y) {alert('Javascript depends on == just embrace it!');}. Tipe primitif memiliki kelas terkait yang menggantikannya ( Number, String) dan Javascript bergantung pada ==operator untuk membuat perbandingan ini natural.
Stijn de Witt
17

Ingatlah bahwa JSLint menerapkan gagasan satu orang tentang apa yang seharusnya menjadi JavaScript yang baik. Anda masih harus menggunakan akal sehat saat menerapkan perubahan yang disarankannya.

Secara umum, membandingkan jenis dan nilai akan membuat kode Anda lebih aman (Anda tidak akan mengalami perilaku yang tidak terduga saat konversi jenis tidak melakukan apa yang menurut Anda seharusnya).

Justin Niessner
sumber
4
Ditambah itu tidak bisa secerdas konteks seperti seorang programmer. Ini hanya bekerja atas dasar bahwa sebagian besar pengguna tersandung oleh konversi jenis otomatis yang melekat dalam sistem (seperti kekerasan - "tolong bantu saya ditekan!")
Rudu
14

Triple-equal berbeda dengan double-equal karena selain memeriksa apakah kedua sisi memiliki nilai yang sama, triple-equal juga memeriksa apakah keduanya memiliki tipe data yang sama.

Begitu ("4" == 4)juga benar, sedangkan ("4" === 4)salah.

Triple-equal juga berjalan sedikit lebih cepat, karena JavaScript tidak perlu membuang waktu melakukan konversi jenis apa pun sebelum memberi Anda jawabannya.

JSLint sengaja ditujukan untuk membuat kode JavaScript Anda seketat mungkin, dengan tujuan mengurangi bug yang tidak jelas. Ini menyoroti hal semacam ini untuk mencoba membuat Anda membuat kode dengan cara yang memaksa Anda untuk menghormati tipe data.

Tetapi hal yang baik tentang JSLint adalah bahwa itu hanya sebuah panduan. Seperti yang mereka katakan di situs, itu akan menyakiti perasaan Anda, bahkan jika Anda adalah programmer JavaScript yang sangat baik. Tetapi Anda tidak perlu merasa wajib untuk mengikuti nasihatnya. Jika Anda telah membaca apa yang dikatakan dan Anda memahaminya, tetapi Anda yakin kode Anda tidak akan rusak, maka tidak ada paksaan pada Anda untuk mengubah apa pun.

Anda bahkan dapat memberi tahu JSLint untuk mengabaikan kategori pemeriksaan jika Anda tidak ingin dibombardir dengan peringatan bahwa Anda tidak akan melakukan apa-apa.

Spudley
sumber
3
Saya tidak bertanya "Apa itu ===", jadi saya tidak yakin mengapa Anda menjawabnya.
Metropolis
8
@ Metropolis: jika tidak ada alasan lain, maka sebagai latar belakang jika ada orang lain yang membaca jawaban yang tidak tahu. Saya memang mencoba menjawab pertanyaan Anda di paragraf setelah itu.
Spudley
@Spudley + 1 untuk informasi tambahan dan berguna
Ben Junior
1
ya, ini 10-100 kali lebih cepat: tes kecepatan
jsperf
8

Kutipan dari http://javascript.crockford.com/code.html :

=== dan! == Operator.

Hampir selalu lebih baik menggunakan operator === dan! ==. Operator == dan! = Melakukan pemaksaan tipe. Secara khusus, jangan gunakan == untuk membandingkan dengan nilai yang salah.

JSLint sangat ketat, 'webjslint.js' mereka bahkan tidak lolos validasinya sendiri.

Lekensteyn
sumber
Klarifikasi yang bagus. Itu benar, tentang webjslint.jstidak memvalidasi - meskipun sebagian besar kesalahan yang saya lihat sekarang berkaitan dengan jarak. Jelas, seseorang harus menggunakan akal sehat dan penilaian yang masuk akal saat meninjau JavaScript menggunakan JSLint.
hotshot309
Penggunaan kata tersebut alwayssecara otomatis mendiskualifikasi kutipan ini sebagai kebijaksanaan. Pemrogram cerdas tidak dogmatis. Mereka menggunakan yang terbaik dalam situasi tertentu. Dan mereka menyambut serta merangkul alat apa pun yang dibangun di dalam inti bahasa, tidak hanya mengabaikannya dengan a just never touch it. Intinya: Kode saya lebih pendek (dan tidak hanya dari menyimpan satu =karakter), sehingga situs saya memuat lebih cepat, dengan biaya bandwidth yang lebih sedikit, sehingga pengguna saya dilayani dengan lebih baik.
Stijn de Witt
4

Jika Anda ingin menguji kepalsuan. JSLint tidak mengizinkan

if (foo == null)

tapi memungkinkan

if (!foo)
nano2nd
sumber
Gunakan ===, yang direkomendasikan JSLint.
clickbait
1
@NarawaGames Solusi ini bisa diterima.
Jawaban ini tidak bagus. Masalahnya adalah bahwa kedua hal ini memiliki arti lain. foo == nullmemeriksa null atau undefined. !foomemeriksa null, undefined, 0 dan string kosong.
Markos
@Markos Jawaban ini dimaksudkan untuk menjadi alternatif yang berguna untuk membuat JSLint senang dan menjaga logika kode Anda tetap utuh, tidak sama persis. Inilah mengapa saya mengawali jawaban dengan "Jika memeriksa kepalsuan"
nano2 pada
3

Untuk membantu menjelaskan pertanyaan ini dan juga menjelaskan mengapa NetBeans (dari) 7.3 mulai menampilkan peringatan ini, ini adalah ekstrak dari tanggapan pelacak bug NetBeans ketika seseorang melaporkan ini sebagai bug:

Ini adalah praktik yang baik untuk menggunakan === daripada == di JavaScript.

Operator == dan! = Melakukan pemaksaan tipe sebelum membandingkan. Ini buruk karena menyebabkan '\ t \ r \ n' == 0 menjadi benar. Ini dapat menutupi kesalahan jenis. JSLint tidak dapat secara andal menentukan apakah == digunakan dengan benar, jadi yang terbaik adalah tidak menggunakan == dan! = Sama sekali dan sebagai gantinya selalu menggunakan operator === dan! == yang lebih andal.

Referensi

EM-Creations
sumber
1
Saya menemukan kesalahan ini sekarang menggunakan Netbeans juga. Aneh bahwa mereka memperlakukan ini dengan peringatan keras karena contoh kasus aneh yang mereka berikan.
omikes
1
Maksud saya, itu benar, tetapi ada banyak kasus penggunaan di mana orang tersebut tahu bahwa dua hal yang dibandingkan akan memiliki tipe yang sama, jadi sepertinya aneh bahwa karena kasus aneh ini di mana pengembalian kereta mungkin dibandingkan dengan nomornya nol adalah alasan mengapa semua penggunaan == dianggap salah. Saya mencari tahu meskipun itu === lebih cepat, karena tidak ada jenis konversi yang dilakukan. Saya terkejut saya tidak menemukan ini sebelum netbeans.
omikes
@oMiKeY Ya, saya mengerti maksud Anda, mereka dapat memberikan contoh yang lebih realistis!
EM-Creations
2

Yah, itu tidak bisa menyebabkan masalah, itu hanya memberi Anda nasihat. Ambil atau tinggalkan. Meski begitu, saya tidak yakin seberapa pintar itu. Mungkin ada konteks yang tidak menampilkannya sebagai masalah.

Rushyo
sumber
1
tapi mengapa kata "yang diharapkan" digunakan? Itu membuatnya terdengar seperti Anda harus selalu melakukan ini.
Metropolis
4
Penilai sedang mencari tanggapan yang valid, saat mencoba memvalidasinya. Jika tidak mendapatkan respons yang valid, maka itu bukan yang diharapkan. Validator memulai dengan asumsi bahwa semuanya baik-baik saja dan kemudian menunjukkan kesalahan saat melintasi kode. Itu tidak selalu memahami apa itu respons tidak valid, itu hanya tahu ketika melihat respons yang tidak valid. Ini juga bisa bekerja sebaliknya, dengan sengaja mencari kode yang buruk sesuai dengan aturan tentang apa yang buruk. Daftar putih vs daftar hitam.
Rushyo
Pertanyaannya adalah "Apakah itu benar-benar masuk akal?". Mengingat pertanyaan itu, ya, memang demikian. Juga, itu lima tahun lalu . Yesus.
Rushyo