Dalam artikel kali ini, saya jelasin beberapa poin dalam pemrograman JavaScript yang sebenernya penting tapi sering ga diperhatiin.
1. Data Numerik
Kebanyakan bahasa pemrograman punya beberapa tipe data numerik ( int
, float
, dll ) tapi JavaScript hanya punya satu yaitu number
.
typeof 100; // number
typeof 10.1; // number
typeof -2.2; // number
Semua angka dalam JavaScript adalah double-precision floating-point. Ini adalah bilangan 64-bit. Detilnya silakan baca sendiri di Wikipedia.
Operasi matematika pake bilangan floating-point akan menghasilkan aproksimasi ( ga 100% akurat ) karena ada pembulatan. Contoh:
var a = (0.1 + 0.2) + 0.3; // 0.6000000000000001
var b = 0.1 + (0.2 + 0.3); // 0.6
2. Hati-hati dengan Konversi Implisit
JavaScript adalah bahasa yang terbilang sangat “pemaaf“. Jadi kalo kita bikin operasi matematika pake data non-numerik, kode kita tetep jalan biarpun hasilnya belum tentu yang kita mau. Ini karena JS secara implisit melakukan konversi data.
10 + true; // 11
"hello" + "world"; // helloworld
"hello" + 1;// hello1
"hello" + true;// hellotrue
2+"3"; // "23" (string)
1+2+"3"; // "33" (string)
1+"2"+3; // "123" (string)
10 * "3"; // 30
Sebenernya istilah aslinya adalah implicit “coercion” (koersi) bukan “conversion” (konversi). Saya terjemahin jadi konversi karena menurut saya lebih gampang dipahami daripada koersi & arti koersi di KBBI kayanya susah dihubungin sama pemrograman.
Truthy & Falsy
Beberapa tipe data bisa dianggap sama dengan boolean
kalo dipake dalam kondisional. Falsy berarti nilainya dianggap seperti false
. Truthy dianggap seperti true
. Contoh:
var a = null;
var b = 0;
if(!a){
console.log('falsy a');
}else{
console.log('truthy a');
}
if(!b){
console.log('falsy b');
}else{
console.log('truthy b');
}
Kalo dijalanin:
falsy a
falsy b
Kalo b
nilainya = hello
:
falsy a
truthy b
Hampir semua data adalah bersifat truthy artinya kalo dipake dalam kondisional (bukan yang strict) selalu dianggap true
. Kecuali, 7 nilai falsy
yaitu: false
, undefined
, null
, NaN
, 0
, -0
, dan ""
.
Jadi, kalo ga pengen ada konversi & supaya kode lebih jelas, biasakan pake operator strict-equality ( pake ===
, bukan ==
).
Kalo kondisional di atas kita ganti pake strict-equality:
var a = null;
var b = 0;
if( a === false){
console.log('falsy a');
}else{
console.log('truthy a');
}
if(b === false){
console.log('falsy b');
}else{
console.log('truthy b');
}
Hasilnya:
truthy a
truthy b
3. Hindari Bikin Objek Global
Apa itu objek global?
Semua objek (variabel / function) yang bisa langsung dibaca/tulis oleh semua skrip. Kode semacam ini baiknya dihindari atau minimal super hati-hati. Kenapa? Karena bisa jadi dia melakukan override variabel a
dan run
yang dibikin skrip lain & sebaliknya bisa di-override juga oleh skrip lain yang datang belakangan.
Contoh, misalnya kita punya dua skrip, yang pertama: car.js
.
//car.js
var manufacturer = 'Toyota';
var year = 2012;
function buy() {
var p = document.createElement('p');
p.textContent = 'buying a car: ' + manufacturer + ' ' + year;
document.body.appendChild(p);
}
var count = 0;
var int = setInterval(function() {
if (count < 10) {
buy();
} else {
clearInterval(int);
}
count++;
}, 1000);
Yang kedua: plane.js
.
//plane.js
var manufacturer = 'Boeing';
var year = 2015;
function buy() {
var p = document.createElement('p');
p.textContent = 'buying a plane: ' + manufacturer + ' ' + year;
document.body.appendChild(p);
}
Dua-duanya kita pake di satu halaman web, hanya saja plane.js
kita muat belakangan.
<!DOCTYPE html>
<html>
<head>
<script src="car.js"></script>
</head>
<body>
<script>
//tunggu 5 detik, terus muat skrip plane.js
setTimeout(function() {
var scr = document.createElement('script');
scr.src = 'plane.js';
document.body.appendChild(scr);
}, 3000);
</script>
</body>
</html>
Live demo kode di atas bisa dilihat di sini
Sebelum plane.js
dimuat, di halaman HTML itu muncul teks:
buying a car: Toyota 2012
Begitu plane.js
dimuat, teksnya berubah jadi:
buying a plane: Boeing 2015
Jadi manufacturer
, year
dan buy
aslinya adalah punya car.js
tapi karena ada scope-nya global, semua di-override oleh plane.js
.
Bayangin kalo ini kejadian di kerjaan Anda. Kacau kan?
Solusinya, atur scope variabel, bisa dengan cara bungkus kode pake closure (function) atau objek ( namespace ).
Pake Closure
Live demo bisa dilihat di sini.
//car.js
(function() {
var manufacturer = 'Toyota';
var year = 2012;
function buy() {
var p = document.createElement('p');
p.textContent = 'buying a car: ' + manufacturer + ' ' + year;
document.body.appendChild(p);
}
var count = 0;
var int = setInterval(function() {
if (count < 10) {
buy();
} else {
clearInterval(int);
}
count++;
}, 1000);
})();
Pake Namespace
JavaScript ga mengenal sintaks namespace kaya di bahasa lain, tapi kita bisa pake Object
.
Demo di sini.
//car.js
var car = {
manufacturer: 'Toyota',
year: 2012,
buy: function() {
var p = document.createElement('p');
p.textContent = 'buying a car: ' + this.manufacturer + ' ' + this.year;
document.body.appendChild(p);
}
}
var count = 0;
var int = setInterval(function() {
if (count < 10) {
car.buy();
} else {
clearInterval(int);
}
count++;
}, 1000);
Bukan berarti ga boleh sama sekali bikin global object, boleh aja tapi kita perlu hati-hati.
4. Selalu deklarasikan variabel lokal
Scope variabel dalam JavaScript adalah statemen function terdekat yang melingkupinya. Tapi syaratnya variabel ini harus dideklarasikan dulu. Kalo nggak, variabel ini bakalan “bocor” ke scope global.
function fn(){
temp = 0; // global temp
}
Kode di atas sama aja dengan begini:
var temp;
function fn(){
temp = 0; // global temp
}
Jadi temp
karena ga dideklarasi sebagai variabel lokal di dalam swap()
, otomatis JS mendeklarasikan variabel ini sebagai global object.
var a = [10,20];
function swap(arr, i, j) {
temp = arr[i]; // global
arr[i] = arr[j];
arr[j] = temp;
}
swap(a,0,1);
console.log(a);// [20,10]
//temp yang bocor dari swap()
console.log(window.temp); // 10</code></pre>
Biarpun pake *closure*, tetep aja bocor.
<pre class="line-numbers" data-line=""><code class="language-javascript">(function(){
var a = [10,20];
function swap(arr, i, j) {
temp = arr[i]; // global temp
arr[i] = arr[j];
arr[j] = temp;
}
swap(a,0,1);
console.log(a);// [20,10]
console.log(window.temp);// 10
})();
Beda kalo kita deklarasikan temp
sebagai variabel lokal:
var a = [10,20];
function swap(arr, i, j) {
var temp = arr[i]; // lokal
arr[i] = arr[j];
arr[j] = temp;
}
swap(a,0,1);
console.log(a);// [20,10]
console.log(window.temp);// undefined
5. Hoisting
Kode di bawah ini pasti error.
function start(){
console.log(a);// "ReferenceError: a is not defined
}
start();
Kalo yang ini ga error padahal a
baru dideklarasikan setelah console.log()
. Kenapa?
function start(){
console.log(a);// undefined
var a = 1;
}
start();
Di atas adalah contoh apa yang disebut hoisting. Kita tahu scope setiap variabel adalah function terdekat yang melingkupinya. Pada waktu sebuah function dijalanin, JS memindahkan semua deklarasi variabel ke atas (hoist) dekat dengan kurung kurawal pembuka function itu.
Jadi kode di atas, sama dengan:
function start(){
var a;// pindahan dari bawah
console.log(a);
a = 1;
}
start();
Sekian. Nanti lanjut di bagian 2.
Also in this category ...
- » Mengenal Hook di ReactJS
- » Rust 101: Hello Rust
- » JS : Pemrograman Asinkron
- » End-to-end Testing dengan The Intern
- » Cara Mudah Pakai Environment Variable dengan Webpack