7 Oktober 2020

Eval: menjalankan kode dari _string_

Fungsi bawaan eval memungkinkan kita untuk menjalankan kode dari sebuah string.

Sintaksnya adalah:

let result = eval(code);

Sebagai contoh:

let code = 'alert("Halo")';
eval(code); // Halo

Sebuah kode yang berupa string bisa panjang, berupa deklarasi fungsi, variabel dan lain-lain.

Hasil dari eval adalah hasil dari peryataan terakhir.

Sebagai contoh:

let value = eval('1+1');
alert(value); // 2
let value = eval('let i = 0; ++i');
alert(value); // 1

Kode yang dievaluasi akan dieksekusi di lingkungan leksikal saat ini, sehingga dapat melihat variabel luar:

let a = 1;

function f() {
  let a = 2;

  eval('alert(a)'); // 2
}

f();

Itu juga dapat mengubah variabel luar:

let x = 5;
eval("x = 10");
alert(x); // 10, nilai diubah

Dalam mode ketat, eval memiliki lingkungan leksikal sendiri. Jadi, fungsi dan variabel yang dideklarasikan di dalam eval, tidak akan terlihat di luar:

// pengingat: dalam contoh yang dijalankan 'use strict' diaktifkan secara bawaan

eval("let x = 5; function f() {}");

alert(typeof x); // undefined (tidak ada variabel)
// fungsi f juga tidak terlihat

Tanpa use strict, eval tidak memiliki lingkungan leksikal sendiri, jadi kita akan melihat x dan f di luar.

Menggunakan “eval”

Dalam pemrograman modern eval jarang digunakan. Sering dikatakan bahwa “eval is evil” atau "eval itu jahat".

Alasannya sederhana: dulu JavaScript adalah bahasa yang jauh lebih lemah, banyak hal yang hanya bisa dilakukan dengan eval. Tapi waktu itu telah berlalu satu dekade yang lalu.

Sekarang, hampir tidak ada alasan untuk menggunakan eval. Jika seseorang menggunakannya, ada kemungkinan mereka dapat menggantinya dengan konstruksi bahasa modern atau JavaScript Module.

Harap dicatat bahwa kemampuannya untuk mengakses variabel luar memiliki efek samping.

Code minifiers (alat yang digunakan sebelum JS masuk ke produksi, untuk mengkompresnya) mengubah nama variabel lokal menjadi lebih pendek (seperti a, b dll) untuk membuat kode menjadi lebih kecil. Biasanya itu aman, tetapi tidak jika eval digunakan, karena variabel lokal dapat diakses dari kode yang dievaluasi dari string. Jadi minifiers tidak melakukan itu untuk mengganti nama semua variabel yang terlihat dari eval. Itu berdampak negatif pada rasio kompresi kode.

Menggunakan variabel lokal luar di dalam eval juga dianggap sebagai praktik pemrograman yang buruk, karena membuat kode lebih sulit dipertahankan.

Ada dua cara untuk terhindar dan aman dari masalah seperti itu.

Jika kode yang dievaluasi tidak menggunakan variabel luar, panggil eval sebagai window.eval(...):

Dengan cara ini, kode akan dijalankan dalam lingkup global:

let x = 1;
{
  let x = 5;
  window.eval('alert(x)'); // 1 (variabel global)
}

Jika kode yang dievaluasi membutuhkan variabel lokal, ubah eval menjadi new Function dan teruskan sebagai argumen:

let f = new Function('a', 'alert(a)');

f(5); // 5

Konstruksi new Function dijelaskan dalam bab Sintaks "new Function". Itu membuat fungsi baru dari sebuah string dan juga dalam lingkup global. Jadi tidak bisa melihat variabel lokal. Tetapi jauh lebih jelas jika meneruskannya sebagai argumen secara eksplisit, seperti pada contoh di atas.

Ringkasan

Pemanggilan eval(code) menjalankan kode dari sebuah string dan mengembalikan hasil dari pernyataan terakhir.

  • Jarang digunakan dalam JavaScript modern, karena biasanya tidak diperlukan.
  • Dapat mengakses variabel lokal luar. Itu dianggap praktik yang buruk.
  • Sebaga gantinya, untuk eval sebuah kode dalam lingkup global, gunakan window.eval(code).
  • Atau, jika kode Anda memerlukan beberapa data dari cakupan luar, gunakan new Function dan teruskan sebagai argumen.

Tugas

pentingnya: 4

Buatlah kalkulator yang meminta operasi aritmatika dan mengembalikan hasilnya.

Tidak perlu memeriksa kebenaran operasi dalam tugas ini. Cukup evaluasi dan kembalikan hasilnya.

jalankan demonya

Mari gunakan eval untuk menghitung rumus matematika:

let expr = prompt("Type an arithmetic expression?", '2*3+2');

alert( eval(expr) );

Pengguna dapat memasukkan teks atau kode apa pun.

Untuk membuat semuanya aman dan membatasinya hanya untuk operasi aritmatika, kita dapat memeriksa expr menggunakan regular expression, sehingga hanya dapat berisi angka dan operator.

Peta tutorial

komentar

baca ini sebelum berkomentar…
  • Jika Anda memiliki saran apa yang harus ditingkatkan - silakan kunjungi kirimkan Github issue atau pull request sebagai gantinya berkomentar.
  • Jika Anda tidak dapat memahami sesuatu dalam artikel – harap jelaskan.
  • Untuk menyisipkan beberapa kata kode, gunakan tag <code>, untuk beberapa baris – bungkus dengan tag <pre>, untuk lebih dari 10 baris – gunakan sandbox (plnkr, jsbin, < a href='http://codepen.io'>codepen…)