Javascriptoo Merupakan Situs Yang memberikan Informasi Tentang Komputer dan Java Scrypt

10 Keanehan Dan Rahasia Tentang JavaScript

10 Keanehan Dan Rahasia Tentang JavaScript – JavaScript Sekaligus aneh namun indah, itu pasti bahasa pemrograman yang akan ditemukan oleh Pablo Picasso. Null tampaknya adalah sebuah objek, sebuah array kosong tampaknya sama dengan false, dan fungsi-fungsi dilingkari seolah-olah itu adalah bola tenis.

10 Keanehan Dan Rahasia Tentang JavaScript

javascriptoo – Artikel ini ditujukan untuk pengembang menengah yang ingin tahu tentang JavaScript yang lebih canggih. Ini adalah kumpulan keanehan JavaScript dan rahasia yang tersimpan dengan baik. Beberapa bagian diharapkan akan memberi Anda wawasan tentang bagaimana keingintahuan ini dapat berguna untuk kode Anda, sementara bagian lain adalah materi WTF murni. Jadi, mari kita mulai.

Baca Juga : Inilah yang Anda Butuhkan Untuk Mempelajari JavaScript Secara Mendalam 

Jenis Data Dan Definisi

1. NULL ADALAH OBYEK

Mari kita mulai dengan keanehan JavaScript favorit semua orang, yang juga terkenal. Null tampaknya adalah sebuah objek, yang sejauh kontradiksi berjalan, ada di atas sana dengan yang terbaik dari mereka. Batal? Sebuah Objek? “Tentunya, definisi nol adalah ketiadaan total nilai yang berarti ,” kata Anda. Anda akan benar.

Meskipun demikian, null tidak dianggap sebagai turunan dari suatu objek. (Jika Anda tidak tahu, nilai dalam JavaScript adalah instance dari objek dasar. Jadi, setiap angka adalah turunan dari Numberobjek, setiap objek adalah turunan dari Objectobjek, dan seterusnya.) Ini membawa kita kembali ke kewarasan, karena jika null adalah ketiadaan nilai, maka itu jelas tidak bisa menjadi turunan dari apa pun. Oleh karena itu, berikut ini dievaluasi menjadi false:

alert(null instanceof Object); //evaluates false

2. NAN ADALAH ANGKA

Anda pikir null menjadi objek itu konyol? Cobalah berurusan dengan gagasan NaN “bukan angka” menjadi angka! Apalagi NaNtidak dianggap sama dengan dirinya sendiri! Apa kepalamu masih sakit?

alert(typeof NaN); //alerts ‘Number’
alert(NaN === NaN); //evaluates false

Bahkan NaNtidak sama dengan apa pun . Satu-satunya cara untuk mengkonfirmasi bahwa ada sesuatu NaNadalah melalui fungsi isNaN().

3. ARRAY TANPA KUNCI == SALAH (TENTANG BENAR DAN SALAH)

Inilah keanehan JavaScript lain yang sangat disukai:

alert(new Array() == false); //evaluates true

Untuk memahami apa yang terjadi di sini, Anda perlu memahami konsep benar dan salah . Ini adalah jenis true/false-lite, yang akan membuat Anda marah jika Anda mengambil jurusan logika atau filsafat.

Saya telah membaca banyak penjelasan tentang apa itu benar dan salah, dan saya merasa yang paling mudah untuk dipahami adalah ini: dalam JavaScript, setiap nilai non-boolean memiliki flag boolean bawaan yang dipanggil ketika nilai diminta untuk berperilaku seperti boolean; seperti, misalnya, ketika Anda membandingkannya dengan boolean.

Karena apel tidak dapat dibandingkan dengan pir, ketika JavaScript diminta untuk membandingkan nilai dari tipe data yang berbeda, pertama-tama ” memaksa ” mereka menjadi tipe data umum. False, zero, null, undefined, string kosong dan NaNsemua akhirnya menjadi false tidak permanen, hanya untuk ekspresi yang diberikan. Contoh penyelamatan:

var someVar = 0;
alert(someVar == false); //evaluates true

Di sini, kami mencoba membandingkan angka 0dengan boolean false. Karena tipe data ini tidak kompatibel, JavaScript secara diam-diam memaksa variabel kita menjadi true atau falsy equivalent , yang dalam kasus 0(seperti yang saya katakan di atas) adalah falsy.

Anda mungkin telah memperhatikan bahwa saya tidak memasukkan array kosong dalam daftar falsies di atas. Array kosong adalah hal yang aneh: mereka benar-benar mengevaluasi kebenaran tetapi , jika dibandingkan dengan boolean, berperilaku seperti falsy. Bingung belum? Dengan alasan yang baik. Contoh lain mungkin?

var someVar = []; //empty array
alert(someVar == false); //evaluates true
if (someVar) alert(‘hello’); //alert runs, so someVar evaluates to true

Untuk menghindari paksaan, Anda dapat menggunakan operator perbandingan nilai dan jenis , ===, (sebagai lawan dari ==, yang hanya membandingkan berdasarkan nilai). Jadi:

var someVar = 0;
alert(someVar == false); //evaluates true – zero is a falsy
alert(someVar === false); //evaluates false – zero is a number, not a boolean

Fiuh. Seperti yang mungkin telah Anda kumpulkan, ini adalah topik yang luas, dan saya sarankan untuk membaca lebih lanjut tentangnya terutama tentang pemaksaan data, yang, meskipun bukan merupakan konsep JavaScript yang unik, tetap menonjol dalam JavaScript.

Saya membahas konsep benar dan salah dan pemaksaan data lebih lanjut di sini. Dan jika Anda benar-benar ingin memahami apa yang terjadi secara internal ketika JavaScript diminta untuk membandingkan dua nilai.

Ekspresi Reguler

4. REPLACE() DAPAT MENERIMA FUNGSI CALLBACK

Ini adalah salah satu rahasia terbaik JavaScript dan tiba di v1.3. Sebagian besar penggunaan replace()terlihat seperti ini:

alert(’10 13 21 48 52′.replace(/d+/g, ‘*’)); //replace all numbers with *

Ini adalah pengganti sederhana: string, tanda bintang. Tetapi bagaimana jika kita ingin lebih mengontrol bagaimana dan kapan penggantian kita dilakukan? Bagaimana jika kita ingin mengganti hanya angka di bawah 30? Ini tidak dapat dicapai dengan ekspresi reguler saja (bagaimanapun juga, semuanya tentang string, bukan matematika). Kita perlu melompat ke fungsi panggilan balik untuk mengevaluasi setiap kecocokan .

alert(’10 13 21 48 52′.replace(/d+/g, function(match) {
return parseInt(match) < 30 ? ‘*’ : match;
}));

Untuk setiap kecocokan yang dibuat, JavaScript memanggil fungsi kita, meneruskan kecocokan ke dalam argumen kecocokan kita. Kemudian, kami mengembalikan tanda bintang (jika nomor yang cocok di bawah 30) atau kecocokan itu sendiri (yaitu tidak ada kecocokan yang terjadi).

5. EKSPRESI REGULER: LEBIH DARI SEKEDAR MENCOCOKKAN DAN MENGGANTI #

Banyak pengembang JavaScript perantara bertahan hanya dengan matchdan replacedengan ekspresi reguler. Tetapi JavaScript mendefinisikan lebih banyak metode daripada keduanya.

Yang menarik adalah test(), yang berfungsi seperti matchkecuali bahwa itu tidak mengembalikan kecocokan: itu hanya mengonfirmasi apakah suatu pola cocok dengan . Dalam hal ini, komputasinya lebih ringan.

alert(/w{3,}/.test(‘Hello’)); //alerts ‘true’

Di atas mencari pola tiga atau lebih karakter alfanumerik, dan karena string Hellomemenuhi persyaratan itu, kita mendapatkan true. Kami tidak mendapatkan kecocokan yang sebenarnya, hanya hasilnya.

Yang juga perlu diperhatikan adalah RegExpobjeknya, yang dengannya Anda dapat membuat ekspresi reguler dinamis, sebagai lawan dari ekspresi statis. Mayoritas ekspresi reguler dideklarasikan menggunakan bentuk pendek (yaitu terlampir dalam garis miring, seperti yang kita lakukan di atas). Namun, dengan begitu, Anda tidak dapat mereferensikan variabel, jadi membuat pola dinamis tidak mungkin . Dengan RegExp(), Anda bisa.

function findWord(word, string) {
var instancesOfWord = string.match(new RegExp(‘b’+word+’b’, ‘ig’));
alert(instancesOfWord);
}
findWord(‘car’, ‘Carl went to buy a car but had forgotten his credit card.’);

Di sini, kami membuat pola dinamis berdasarkan nilai argumen word. Fungsi mengembalikan berapa kali wordmuncul dalam string sebagai kata dalam dirinya sendiri (yaitu bukan sebagai bagian dari kata lain). Jadi, contoh kami kembali carsekali, mengabaikan cartoken dalam kata-kata Carldan card. Ini memaksa ini dengan memeriksa batas kata ( b) di kedua sisi kata yang kita cari.

Karena RegExpditentukan sebagai string, bukan melalui sintaks garis miring, kita dapat menggunakan variabel dalam membangun pola. Ini juga berarti, bagaimanapun, bahwa kita harus meng-escape karakter khusus apa pun, seperti yang kita lakukan dengan karakter batas kata kita.

Fungsi Dan Ruang Lingkup

6. ANDA DAPAT MEMALSUKAN LINGKUP

Ruang lingkup di mana sesuatu dieksekusi mendefinisikan variabel apa yang dapat diakses. JavaScript yang berdiri sendiri (yaitu JavaScript yang tidak berjalan di dalam suatu fungsi) beroperasi dalam lingkup global windowobjek, yang dapat diakses oleh semuanya; sedangkan variabel lokal yang dideklarasikan di dalam fungsi hanya dapat diakses di dalam fungsi itu, bukan di luar.

var animal = ‘dog’;
function getAnimal(adjective) { alert(adjective+’ ‘+this.animal); }
getAnimal(‘lovely’); //alerts ‘lovely dog’;

Di sini, variabel dan fungsi kami dideklarasikan dalam lingkup global (yaitu pada window). Karena ini selalu menunjuk ke ruang lingkup saat ini, dalam contoh ini menunjuk ke window. Oleh karena itu, fungsi mencari window.animal, yang ditemukannya. Sejauh ini biasa saja. Tetapi kita sebenarnya dapat menipu fungsi kita dengan berpikir bahwa itu berjalan dalam lingkup yang berbeda , terlepas dari lingkup alaminya sendiri. Kami melakukan ini dengan memanggil call()metode bawaannya, bukan fungsi itu sendiri:

var animal = ‘dog’;
function getAnimal(adjective) { alert(adjective+’ ‘+this.animal); };
var myObj = {animal: ‘camel’};
getAnimal.call(myObj, ‘lovely’); //alerts ‘lovely camel’

Di sini, fungsi kita tidak berjalan windowtetapi aktif myObj ditentukan sebagai argumen pertama dari metode panggilan. Pada dasarnya, call()berpura-pura bahwa fungsi kami adalah metode myObj(jika ini tidak masuk akal, Anda mungkin ingin membaca tentang sistem pewarisan prototipe JavaScript). Perhatikan juga bahwa setiap argumen yang kita berikan call()setelah yang pertama akan diteruskan ke fungsi kita oleh karena itu kita meneruskan lovelysebagai adjectiveargumen kita.

Saya pernah mendengar pengembang JavaScript mengatakan bahwa mereka telah bertahun-tahun tanpa perlu menggunakan ini, paling tidak karena desain kode yang baik memastikan bahwa Anda tidak memerlukan asap dan cermin ini. Meskipun demikian, itu tentu saja menarik.

Selain itu, apply()melakukan pekerjaan yang sama dengan call(), kecuali bahwa argumen ke fungsi ditentukan sebagai array, bukan sebagai argumen individual. Jadi, contoh penggunaan di atas apply()akan terlihat seperti ini:

getAnimal.apply(myObj, [‘lovely’]); //func args sent as array

7. FUNGSI DAPAT MENGEKSEKUSI SENDIRI

Tidak dapat disangkal:

(function() { alert(‘hello’); })(); //alerts ‘hello’

Sintaksnya cukup sederhana: kita mendeklarasikan sebuah fungsi dan segera memanggilnya seperti kita memanggil fungsi lain, dengan ()sintaks. Anda mungkin bertanya-tanya mengapa kami melakukan ini. Sepertinya ada kontradiksi dalam istilah: fungsi biasanya berisi kode yang ingin kita jalankan nanti, bukan sekarang, jika tidak, kita tidak akan memasukkan kode ke dalam fungsi.

Salah satu penggunaan fungsi self-executing (SEF) yang baik adalah untuk mengikat nilai variabel saat ini untuk digunakan di dalam kode yang tertunda, seperti panggilan balik ke acara, batas waktu, dan interval. Inilah masalahnya:

var someVar = ‘hello’;
setTimeout(function() { alert(someVar); }, 1000);
var someVar = ‘goodbye’;

Pemula di forum selalu bertanya mengapa alertdi timeoutkatakan goodbyedan tidak hello. Jawabannya adalah timeoutfungsi callback persis seperti itu panggilan balik sehingga tidak mengevaluasi nilai someVarsampai dijalankan. Dan saat itu, someVarsudah lama ditimpa oleh goodbye.

SEF memberikan solusi untuk masalah ini. Alih-alih menentukan callback batas waktu secara implisit seperti yang kita lakukan di atas, kita mengembalikannya dari SEF, di mana kita meneruskan nilai saat ini someVarsebagai argumen.

Secara efektif, ini berarti kita memasukkan dan mengisolasi nilai saat ini dari someVar, melindunginya dari apa pun yang terjadi pada variabel aktual someVarsetelahnya . Ini seperti mengambil foto mobil sebelum Anda menyemprotnya kembali; foto tidak akan diperbarui dengan warna yang disemprot ulang; itu akan selamanya menunjukkan warna mobil pada saat foto itu diambil.

var someVar = ‘hello’;
setTimeout((function(someVar) {
return function() { alert(someVar); }
})(someVar), 1000);
var someVar = ‘goodbye’;

Kali ini, ia memperingatkan hello, seperti yang diinginkan, karena memperingatkan versi terisolasi dari someVar(yaitu argumen fungsi, bukan variabel luar).

Peramban

8. FIREFOX MEMBACA DAN MENGEMBALIKAN WARNA DALAM RGB, BUKAN HEX

Saya tidak pernah benar-benar mengerti mengapa Mozilla melakukan ini. Tentunya ia menyadari bahwa siapa pun yang menginterogasi warna yang dihitung melalui JavaScript tertarik pada format hex dan bukan RGB. Untuk memperjelas, berikut ini contohnya:

Hello, world!

<script>
var ie = navigator.appVersion.indexOf(‘MSIE’) != -1;
var p = document.getElementById(‘somePara’);
alert(ie ? p.currentStyle.color : getComputedStyle(p, null).color);
</script>

Sementara sebagian besar browser akan mengingatkan ff9900, Firefox kembali rgb(255, 153, 0), setara RGB. Banyak fungsi JavaScript di luar sana untuk mengonversi RGB ke hex.

Perhatikan bahwa ketika saya mengatakan warna yang dihitung, saya mengacu pada warna saat ini, terlepas dari bagaimana itu diterapkan pada elemen . Bandingkan ini dengan gaya, yang hanya membaca properti gaya yang ditetapkan secara implisit dalam atribut gaya elemen. Juga, seperti yang akan Anda perhatikan pada contoh di atas, IE memiliki metode berbeda untuk mendeteksi gaya yang dihitung dari browser lain.

Selain itu, css()metode jQuery mencakup deteksi terkomputasi semacam ini, dan mengembalikan gaya namun diterapkan ke elemen: secara implisit atau melalui pewarisan atau apa pun. Oleh karena itu, Anda akan relatif jarang membutuhkan yang asli getComputedStyledan currentStyle.

9. 0.1 + 0.2 !== 0.3

Yang ini adalah keanehan tidak hanya di JavaScript; itu sebenarnya masalah yang berlaku dalam ilmu komputer, dan itu mempengaruhi banyak bahasa. Outputnya adalah 0,3000000000000000004. Ini ada hubungannya dengan masalah yang disebut presisi mesin . Ketika JavaScript mencoba mengeksekusi baris di atas, itu mengubah nilai menjadi setara binernya.

Di sinilah masalahnya dimulai. 0.1 sebenarnya bukan 0.1 melainkan ekuivalen binernya, yang merupakan nilai hampir mendekati (tetapi tidak identik) . Intinya, segera setelah Anda menulis nilainya, mereka pasti akan kehilangan presisinya. Anda mungkin hanya menginginkan dua desimal sederhana, tetapi apa yang Anda dapatkan, seperti yang dicatat oleh Chris Pine, adalah aritmatika titik-mengambang biner. Semacam ingin teks Anda diterjemahkan ke dalam bahasa Rusia tetapi mendapatkan bahasa Belarusia. Serupa, tapi tak sama.

Lebih banyak yang terjadi di sini, tetapi di luar cakupan artikel ini (belum lagi kemampuan matematika penulis ini).

Solusi untuk masalah ini adalah favorit di forum ilmu komputer dan pengembang. Pilihan Anda, pada satu titik, tergantung pada jenis perhitungan yang Anda lakukan. Pro dan kontra dari masing-masing berada di luar cakupan artikel ini, tetapi pilihan umum adalah antara yang berikut:

Mengonversi ke bilangan bulat dan menghitungnya, lalu mengonversi kembali ke desimal sesudahnya; atau
Tweak logika Anda untuk memungkinkan rentang daripada hasil tertentu .

Jadi, misalnya, daripada…

var num1 = 0.1, num2 = 0.2, shouldEqual = 0.3;
alert(num1 + num2 == shouldEqual); //false

Diterjemahkan, ini mengatakan bahwa karena 0,1 + 0,2 tampaknya bukan 0,3, periksa apakah itu lebih atau kurang 0,3 khususnya, dalam kisaran 0,001 di kedua sisinya. Kelemahan yang jelas adalah bahwa, untuk perhitungan yang sangat tepat, ini akan mengembalikan hasil yang tidak akurat.

10. TIDAK TERDEFINISI DAPAT DIDEFINISIKAN

OK, mari kita akhiri dengan yang konyol, agak ngawur. Aneh kedengarannya, undefinedsebenarnya bukan kata yang dicadangkan dalam JavaScript, meskipun memiliki arti khusus dan merupakan satu-satunya cara untuk menentukan apakah suatu variabel tidak terdefinisi. Jadi:

var someVar;
alert(someVar == undefined); //evaluates true

Sejauh ini biasa saja. Tetapi:

undefined = “I’m not undefined!”;
var someVar;
alert(someVar == undefined); //evaluates false!

Anda juga dapat memeriksa daftar Mozilla untuk semua kata yang dicadangkan dalam JavaScript untuk referensi di masa mendatang.