Tips JavaScript Bagian 1 – Tipe Data dan Variabel

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 implicitcoercion” (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

Biarpun pake closure, tetep aja bocor.

(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 ...


Leave a Reply

Your email address will not be published. Required fields are marked *