Tag: JavaScript

  • Perbedaan Operator perbandingan == dan === dalam javaScript

    JavaScript memiliki 2 operator untuk membandingkan dua buah nilai, yaitu:

    1. Strict Equality Operator ===. Operator yang ketat, lurus, tanpa basa-basi.
    2. Lenient (Normal) Equality Operator ==. Lebih sabar, bisa memaafkan kesalahan programer saat membandingkan 2 tipe data yang berbeda.

    Perbedaannya adalah yang pertama hanya mempertimbangkan jika 2 buah nilai yang dibandingkan meiliki tipe data yang sama, selain itu maka bernilai false. Sedangkan yang kedua akan memaksakan konversi nilai yang berbeda sebelum membandingkannya seperti pada tipe pertama.

    Semua programer JavaScript sepakat untuk hanya menggunakan tipe pertama. Alasannya karena konversi otomatis mungkin menimbulkan hasil yang tidak dikehendaki. Karena sifat pemaafnya ini, kesalahan yang dibuat sang programer akan tersembunyi sampai akhirnya timbul masalah.

    Strict Equal ===
    Membandingkan 2 buah nilai yang berbeda tipe datanya dengan operator ===, sudah pasti bernilai false. Jika kedua buah nilai memiliki tipe data yang sama, pernyataan-pernyataan di bawah ini akan bernilai true.

    • undefined === undefined
    • null === null
    • x === x
    • +0 === -0
    • false === false
    • NAN !== NAN

    Nilai nol (0) baik positif atau negatif adalah sama nilainya. Untuk NAN, tidak bisa dibandingkan dengan nilai apapun termasuk dengan nilai NAN sendiri. Tipe data string dan number dibandingkan seperti biasa.

    Equal ==
    Membandingkan 2 buah nilai, jika keduanya memiliki tipe data sama, bandingkan dengan ‘===’. Selain itu:

    1. undefined == null
    2. number dibandingkan dengan string, konversi string ke number
    3. boolean dibandingkan non-boolean, konversi boolean ke number, kemudian bandingkan (angka 0 bernilai false, 1 true)
    4. membandingkan string atau number dengan object, konversi object ke tipe data primitif, kemudian bandingkan

    Contoh-contoh yang sering dijumpai:

    0 == false //true
    1 == true //true
    2 == true //false
    2 ? true : false //true, karena 2 !== 0
    
    "" == 0 //true
    "" == false //true
    
    1 == "1" //true
    "1" == true //true
    
    "2" == true //false
    "true" == true //false
    "2" ? true : false //true, karena string tidak kosong
    "abc" == new String("abc") //true, tipe object dikonversi ke tipe primitif string
    

    Satu yang agak membingunkan di atas adalah pada pernyataan if atau pada operator ternary, angka lebih besar dari 1 bernilai true, namun bernilai false dalam perbandingan.

    Berikut ini adalah beberapa contoh perbandingan dengan ‘==’ yang terkenal membingungkan dan dapat menimbulkan kesalahan.

    '' == '0' // false
    0 == '' // true
    0 == '0' // true
    
    false == 'false' // false
    false == '0' // true
    
    null == undefined // true
    false == undefined // false
    false == null // false
    
    ' \t\r\n ' == 0 // true
    

    Sumber: http://www.2ality.com/2011/06/javascript-equality.html

  • Memanipulasi URL pada Status Bar Browser

    Mungkin teknik ini hanya digunakan oleh para penjahat dunia maya. Orang yang merasa perlu untuk menyembunyikan apa yang seharusnya bebas diketahui publik. Penting bagi kita untuk mengetahui teknik yang digunakan oleh para penjahat untuk melindungi diri bukan untuk sebaliknya. Biasanya ini digunakan untuk menyembunyikan/memanipulasi link referal atau sebagai langkah awal kejahatan phishing.

    Ketika kita menyorotkan mouse pada sebuah tautan (link), misalnya ini, maka akan muncul URL dari tautan tersebut pada status bar. Biasanya terletak pada pojok kiri bawah sebuah browser.

    Sebuah tautan yang benar adalah menggunakan tag HTML <a> dengan atribut href dan title. Atribut href wajib ada karena dibutuhkan sebagai tujuan sebuah tautan dan memunculkan URL pada status bar, sedangkan title opsional.

    <a href="http://sibudi.net" title="Websiteku">klik di sini</a>
    

    Berikut ini adalah 3 teknik yang digunakan untuk menyembunyikan atau memanipulasi tautan.

    Cara pertama

    <a style="cursor:pointer" onClick="location.href='http://sibudi.net'" >klik di sini</a>
    

    Pada kode di atas, atribut href sengaja tidak ditulis. Dalam keadaan normal hal tersebut tidak berbahaya, hanya akan menampilkan tulisan “klik di sini” pada browser dan tidak bisa diklik. Namun dengan tambahan sedikit kode JavaScript di atas, tautan di atas akan mengarah pada “http://sibudi.net” tanpa dapat dilihat tujuannya oleh pengguna awam.

    Untuk lebih meyakinkan dapat ditambahkan inline css cursor:pointer yang akan mengubah pointer menjadi gambar tangan. Bisa juga ditambahkan text-decoration:underline dan color sesuai dengan warna yang digunakan pada browser.

    Cara kedua (hanya bekerja pada browser IE):

    <a href="http://sibudi.net" onMouseOver="window.status='http://www.google.com'; return true" onMouseOut="window.status=''">klik di sini</a>
    

    Tautan di atas tidak lagi hanya menyembunyikan URL tapi memanipulasi URL. Jadi pada status bar tertulis “http://google.com” padahal jika diklik akan menuju ke “http://sibudi.net”. Namun teknik itu tidak akan bekerja pada browser selain IE.

    Cara ketiga

    <script>
    function redirect(URL) {
    
      document.location = URL;
      return false;
    }
    </script>
    
    <a href="http://google.com" onClick="return redirect('http://sibudi.net');">klik di sini</a>
    

    Teknik ketiga adalah gabungan dari 2 teknik sebelumnya, yaitu menggunakan atribut href dan onClick. Seperti yang kita tau, atribut href akan memunculkan URL pada status bar. Ketika tautan di atas diklik, maka akan membangkitkan event onClick dan memanggil fungsi JavaScript redirect.

    Perlu dicatat bahwa ketiga teknik di atas sangat bergantung pada JavaScript. Jadi tidak akan bekerja pada browser yang di-disable Javascript-nya. Tautan akan tetap mengarah sesuai pada atribut href dan hanya berupa teks biasa jika atribut href tidak ada. Untuk menangani masalah JavaScript ini, bisa mengacu pada tulisan menangani browser dengan JavaScript disable.

  • Jangan Gunakan Autofocus pada Form Login

    Autofocus adalah salah satu atribut baru yang dikenal pada HTML 5. Autofocus adalah sebuah atribut boolean (true/false). Atribut autofocus akan secara otomatis mengatur fokus ke kotak input yang telah ditentukan. Jadi bisa dibilang autofocus menghemat 1 kali mouse klik.

    Contoh website yang menggunakan autofocus pada kotak input adalah mesin pencari Google. Ketika ingin mencari sesuatu melalui Google, kita tidak perlu mengeklik pada kotak input untuk bisa mengetik kata kuncinya. Secara otomatis kursor berkedip di kotak input, pertanda bisa langsung mengetik di situ.

    Di bawah ini adalah potongan kode untuk menunjukan penggunaan autofocus.

    <label for="nama">Nama </label><input id="nama" name="nama" type="text" autofocus="autofocus"/>
    

    Pada atribut boolean seperti autofocus, pengisian nilai tidak mutlak diperlukan, jadi penulisan seperti di bawah ini juga benar.

    <label for="nama">Nama </label><input id="nama" name="nama" type="text" autofocus/>
    

    Semua browser moderen mendukung fitur ini, kecuali Internet Explorer. Untuk mengimplementasikan fitur ini pada browser yang tidak mendukung autofocus, maka bisa digunakan JavaScript. Namun bukan itu yang menjadi masalah di sini. Perhatikan potongan kode di bawah ini.

    <label for="nama">Nama </label><input id="nama" name="nama" type="text" <strong>autofocus="autofocus"</strong>/> <br />
    <label for="password">Password </label><input id="password" name="password" type="password" />
    

    Ada sebuah halaman yang berisi sebuah form login. Salah satu kotak input-nya memiliki atribut autofocus. Jadi kursor akan secara otomatis berkedip di kotak “nama” setelah halaman selesai dimuat seutuhnya. Namun beberapa pengguna tidak sabar atau tidak mengetahui fitur ini, sehingga mereka mengeklik pada kotak input “nama” tanpa menunggu halaman dimuat seutuhnya. Akibatnya, ketika pengguna sampai pada kotak input “password”, lalu halaman selesai dimuat seutuhnya, maka kursor akan berpindah lagi ke kotak input “nama”.

    Bayangkan jika seseorang sedang mengetik di kotak password lalu tiba-tiba kursor berpindah ke kotak input “nama” yang notabene bertipe text. Password-nya akan tercetak di kotak input “nama” tanpa samaran. Hal ini fatal karena password bisa dilihat oleh orang lain yang kebetulan lewat di dekat kita.

    autofocus text input

    Website yang menerapkan fitur ini pada form login contohnya adalah Facebook, sedangkan yang tidak adalah Twitter.

  • Autentikasi dan Mengambil Data Pengguna dengan Facebook SDK

    Tutorial ini sudah banyak didokumentasikan di blog-blog baik dalam dan luar negeri, tetapi sangat membingungkan bagi saya. Beberapa tutorial menggunakan JavaScript SDK, sedangkan yang lain menggunakan PHP SDK. Belum lagi, banyak di antaranya yang sudah kadaluarsa dan diperburuk oleh revisi dari Facebook yang tidak menentu.

    Hal lain yang juga membingungkan adalah perbedaan tampilan kotak dialog yang menanyakan izin untuk mengakses data-data. Bandingkan tampilan dialog yang saya ambil dari Facebook Developers Guide berikut dengan yang dihasilkan dari tutorial ini.

    login with facebook

    Sebenarnya hanya ada 2 hal dasar yang menjadi alasan untuk menggunakan Facebook SDK.
    1. Kita mempunyai sistem “register” dan “login” sendiri, dan ingin menambahkan “Login with Facebook” sebagai pilihan bagi pengguna yang malas untuk mendaftar secara normal.
    2. Kita membutuhkan data-data pengguna yang sudah dicatat dengan baik oleh Facebook, tentunya dengan persetujuan pemilik akun.

    Dokumentasi dan kode sumber yang ada di Facebook Developers Guide sudah lengkap, namun susah diikuti dan tidak semuanya saya butuhkan. Tutorial ini akan menggabungkan Javascript SDK dan PHP SDK, karena cara ini menurut saya paling sederhana untuk memenuhi 2 kebutuhan dasar di atas.

    Langkah-langkah untuk menghubungkan website dengan Facebook SDK adalah:
    1. Daftarkan website pada halaman Facebook Developers, di situ akan diperoleh “App ID” dan “App Secret”.
    2. Buat sebuah table pada database untuk menyimpan data-data pengguna dari Facebook. Field-nya sesuai kebutuhan saja, contoh: nama, password, email, tipe (password yang dimaksud di sini bukan password facebook dan tipe akan berisi “facebook” jika data diambil dari facebook dan “normal” jika tidak).
    3. Download Facebook SDK. Ambil semua isi folder “src” (kita hanya membutuhkan ini).
    4. Tombol login bisa menggunakan tag HTML biasa

    <div class="fb-login-button">

    atau menggunakan JavaScript SDK.

    <fb:login-button>

    Dengan ini kita bisa mengakses data-data pengguna yang diatur secara publik (tidak disembunyikan), misalnya id, nama, jenis kelamin. Data-data yang tidak bisa diakses publik harus ditulis ke dalam atribut scope.

    <fb:login-button scope="email, read_stream"></fb:login-button>

    5. Deklarasikan Facebook object di paling atas halaman. Jangan lupa isi “App ID” dan “App secret”. Kemudian ambil data-data pengguna (sudah termasuk yang ditulis di atribut scope tadi) dengan Facebook API.

    require_once("facebook.php");
    
    $config = array();
    $config['appId'] = '';
    $config['secret'] = '';
    
    $facebook = new Facebook($config);
    
    $user = $facebook->getUser();
    
    if ($user) {
      try {
        $user_profile = $facebook->api('/me');
      } catch (FacebookApiException $e) {
        error_log($e);
        $user = null;
      }
    }
    

    6. Terakhir, data-data yang sudah diperoleh dari Facebook API bisa diolah sesuai keinginan. Untuk lebih memahami, baca komentar yang ada pada kode sumber.

    <?php if($user) { ?>
    
    //tampilkan foto dan nama user		      
    <img src="https://graph.facebook.com/<?php echo $user; ?>/picture">
    <?=$user_profile['name']?>
    		    
    <?php
    //ambil data-data yang ingin disimpan
    $fb_id = $user_profile['id'];
    $username = $user_profile['username'];
    $email = $user_profile['email'];
    
    //periksa apakah user sudah pernah login
    $insert = true;
    if (/*query untuk memeriksa apakah data sudah ada di database*/)
        $insert = false;
    
    //jika pertama kali login, masukan data user ke database
    if($insert) {
        /*query INSERT untuk memasukan data ke database*/
    }
    
    //login user
    /* kode untuk login user dan SESSION */
    ?>
    
    <?php } else { ?>
    <fb:login-button scope="email, read_stream"></fb:login-button>
    <?php } ?>
    

    Gabungkan langkah ke-5 dan ke-6 serta tambahkan JavaScript SDK. Akhirnya kita akan memperoleh data dalam bentuk array setelah login dengan Facebook.

    <?php 
    require_once("facebook.php");
    
    $config = array();
    $config['appId'] = 'isi_dengan_app_id';
    $config['secret'] = 'isi_dengan_app_secret';
    
    $facebook = new Facebook($config);
    
    $user = $facebook->getUser();
    
    if ($user) {
      try {
        $user_profile = $facebook->api('/me');
      } catch (FacebookApiException $e) {
        error_log($e);
        $user = null;
      }
    }
    
    if ($user) { ?>
    
    <pre>
    <?php print_r($user_profile) ?>
    </pre>
    
    <?php } else { ?>
    <fb:login-button scope="email, read_stream"></fb:login-button>
    <?php } ?>
    <div id="fb-root"></div>
    
    <script>
    window.fbAsyncInit = function() {
      FB.init({
        appId: '<?php echo $facebook->getAppID() ?>',
        cookie: true,
        xfbml: true,
        oauth: true
      });
      FB.Event.subscribe('auth.login', function(response) {
        window.location.reload();
      });
      FB.Event.subscribe('auth.logout', function(response) {
        window.location.reload();
      });
    };
    (function() {
      var e = document.createElement('script'); e.async = true;
      e.src = document.location.protocol +
        '//connect.facebook.net/en_US/all.js';
      document.getElementById('fb-root').appendChild(e);
    }());
    </script>
    
  • JavaScript dan Object Oriented Programming (OOP) Bagian 3

    Sedikit kilas balik pada catatan sebelumnya tentang class, bahwa class memiliki property dan method. Setelah sebuah class didefinisikan, maka class tersebut dapat digunakan berulang kali. Caranya adalah dengan menggunakan object constructor (berikutnya akan ditulis constructor). Constructor sebenarnya adalah sebuah function, bedanya adalah constructor dipanggil menggunakan kata kunci new.

    var Anjing = function(umur_anjing_saya, warna_anjing_saya) {
      this.umur = umur_anjing_saya;
      this.warna = warna_anjing_saya;
    };
     
    var heli = new Anjing(5, "putih");
    var luki = new Anjing(3, "hitam");
    

    Pada contoh di atas, function “Anjing” adalah sebuah constructor. Constructor dapat dipanggil berulang kali untuk menciptakan object baru dengan kata kunci new. Jadi constructor adalah sebuah cetak biru dari sebuah object, bukan object itu sendiri.

    Lalu bagaimana cara untuk mengubah cetak biru tersebut, katankanlah untuk menambah fungsi/fitur pada class “Anjing”? Kita bisa menambahkan method setelah memanggil constructor.

    var Anjing = function(umur_anjing_saya, warna_anjing_saya) {
      this.umur = umur_anjing_saya;
      this.warna = warna_anjing_saya;
    };
     
    var heli = new Anjing(5, "putih");
    heli.suara = function() {
      console.log("guk");
    };
    heli.suara();
    
    var luki = new Anjing(3, "hitam");
    luki.suara(); //error
    

    Pada baris ketujuh dapat dilihat method “suara” ditambahkan pada object “heli”. Perhatikan apa yang akan terjadi jika luki juga mencoba untuk bersuara seperti ini luki.suara();. Meskipun luki termasuk ke dalam class “Anjing”, tetapi dia tidak tau bagaimana untuk bersuara karena hanya heli yang ditambahi method “suara”. Jadi ajarkan luki untuk bersuara seperti heli, tapi dengan suara yang agak beda, misalnya “auu”.

    var Anjing = function(umur_anjing_saya, warna_anjing_saya) {
      this.umur = umur_anjing_saya;
      this.warna = warna_anjing_saya;
    };
     
    var heli = new Anjing(5, "putih");
    heli.suara = function() {
      console.log("guk");
    };
    heli.suara();
    
    var luki = new Anjing(3, "hitam");
    luki.suara = function() {
      console.log("auu");
    };
    luki.suara();
    

    Object juga bisa digunakan sebagai argumen pada suatu function, karena pada dasarnya suatu object adalah variabel yang lebih kompleks.

    var Anjing = function(suara) {
      this.suara = suara;
    };
    
    function keluarkanSuara(anjing) {
      console.log(anjing.suara);
    };
    
    var heli = new Anjing("guk");
    keluarkanSuara(heli);
    

    Cara yang lebih elegan untuk menambah fungsi/fitur pada sebuah cetak biru objek adalah dengan menggunakan kata kunci prototype. Prototype mewakili sifat pewarisan (inheritance) pada JavaScript. Alih-alih menggunakan heli.suara untuk menambahkan method pada object “heli”, gunakan Anjing.prototype.suara.

    var Anjing = function(umur_anjing_saya, warna_anjing_saya) {
      this.umur = umur_anjing_saya;
      this.warna = warna_anjing_saya;
    };
     
    var heli = new Anjing(5, "putih");
    Anjing.prototype.suara = function() {
      console.log("guk");
    };
    heli.suara();
    
    var luki = new Anjing(3, "hitam");
    luki.suara();
    

    Sekarang “luki” bisa menggunakan method “suara” seperti pada “heli” tanpa harus diajarkan terlebih dahulu, karena sudah ditambahkan pada class “Anjing”.

    Kegunaan penting dari prototype adalah agar programer tidak perlu menulis ulang kode yang sudah ada di class lain. Misal pada contoh berikut kita ingin membuat class “Kucing”, yang memiliki property atau method yang sama dengan class “Anjing”.

    var Kucing = function(umur_kucing_saya, warna_kucing_saya) {
      this.umur = umur_kucing_saya;
      this.warna = warna_kucing_saya;
      this.suara = function() {
        console.log("mew");
      };
    };
    

    Pada contoh di atas tampak bahwa class “Kucing” menggunakan property “umur” dan “warna” yang juga ada pada class “Anjing”. Untuk menghindari hal ini maka ciptakan suatu induk, dan gunakan prototype untuk menurunkan property dan method untuk anak-anaknya.

    var Hewan = function(suara_hewan) {
      this.suara = function() {
        console.log(suara_hewan);
      };
    };
    
    var Anjing = function(umur_anjing, warna_anjing) {
      this.umur = umur_anjing;
      this.warna = warna_anjing;
    };
    
    Anjing.prototype = new Hewan("guk");
    
    var heli = new Anjing(5, "putih");
    heli.suara();
    

    Pada contoh di atas, meskipun “heli” sebagai “Anjing” tidak memiliki method “suara”, tetapi tetap bisa memanggil method “suara” karena mendapat pewarisan dari class “Hewan”.

    Pewarisan juga bisa dilakukan secara bertingkat (prototype chain). Misalnya kita mempunyai seekor anjing bernama heli. Heli ini termasuk anjing, tetapi juga termasuk hewan. Jadi, class “Heli” bisa diturunkan dari class “Anjing”, dan class “Anjing” diturunkan dari class “Hewan”. Mari lanjutkan dan sempurnakan kode di atas sehingga memiliki sifat enkapsulasi dan pewarisan.

    var Hewan = function(suara_hewan) {
      var suara = suara_hewan;
      this.bersuara = function() {
        return console.log(suara);
      };
    };
    
    var Anjing = function(umur_hewan, warna_hewan) {
      var umur = umur_hewan;
      var warna = warna_hewan;
      this.berumur = function() {
        return console.log(umur);
      };
      this.berwarna = function() {
        return console.log(warna);
      };
    };
    
    var Heli = function(hobi_heli) {
      var hobi = hobi_heli;
      this.berhobi = function() {
        return console.log(hobi);
      };
    };
    
    Anjing.prototype = new Hewan("guk");
    Heli.prototype = new Anjing(5, "putih");
    
    var anjing_saya = new Heli("jogging");
    anjing_saya.berhobi(); //jogging
    anjing_saya.berumur(); //5
    anjing_saya.bersuara(); //guk