Cú pháp new Function trong JavaScript

Cập nhật ngày 29/12/2021

Cú pháp new Function trong JavaScript là một cách khác để định nghĩa hàm. Cách này ít khi được sử dụng, nhưng đôi khi lại rất hữu ích.

Cú pháp new Function

Cú pháp new Function để định nghĩa hàm như sau:

let func = new Function([arg1, arg2, ...argN], functionBody);

Trong đó:

  • [arg1, arg2, ...argN]: là danh sách các tham số truyền vào hàm.
  • functionBody: là string dùng để mô tả hàm.

Ví dụ hàm tính tổng sau nhận vào hai số ab rồi trả về tổng a + b:

let sum = new Function("a", "b", "return a + b");

console.log(sum(1, 2)); // 3

Hoặc hàm không có tham số truyền vào:

let sayHi = new Function('console.log("Hello")');

sayHi(); // Hello

Điểm khác nhau quan trọng giữa cú pháp new Function trong JavaScript với các cách định nghĩa hàm khác là:

  • Cú pháp new Function sử dụng string để định nghĩa thân hàm.
  • Quá trình định nghĩa hàm được thực hiện runtime (trong thời điểm chạy chương trình).

Với tất cả các cách khác, bạn phải định nghĩa hàm ngay từ đầu. Nhưng cú pháp new Function lại có thể chuyển string thành hàm.

Điều này cho phép bạn định nghĩa hàm bằng cách nhận string từ server (hoặc nguồn khác) rồi thực thi hàm:

let str = /*... nhận được từ server ...*/

// khởi tạo hàm từ string nhận được trên
let func = new Function(str);

// thực thi hàm
func();

Mối liên quan với closure

Thông thường, một hàm trong JavaScript sẽ lưu những thông tin của môi trường - nơi mà hàm được tạo ra, đó chính là Lexical Environment.

Nếu một hàm được định nghĩa thông qua cú pháp new Function thì lại khác. Hàm này không lưu thông tin của môi trường nơi hàm tạo ra mà lại lưu thông tin của môi trường global, ví dụ:

window.value = "test from window";

function getFunc() {
  let value = "test from getFunc";

  let func = new Function("console.log(value)");

  return func;
}

getFunc()(); // test from window

Trong ví dụ trên, hàm func được tạo ra bên trong hàm getFunc nhưng lại không nhìn thấy biến value bên ngoài.

Nói cách khác, biến value ở câu lệnh console.log(value) sẽ được tham chiếu đến đối tượng global (với trình duyệt thì đó là đối tượng window).

So sánh với cách định nghĩa hàm thông thường:

window.value = "test from window";

function getFunc() {
  let value = "test from getFunc";

  let func = function () {
    console.log(value);
  };

  return func;
}

getFunc()(); // "test from getFunc" - giá trị của value lấy ở bên ngoài

Đặc điểm trên của cú pháp new Function trong JavaScript có vẻ lạ, nhưng lại rất hợp lý.

Tưởng tượng bạn cần phải tạo một hàm từ string. Mà nội dung của hàm lại không biết trước nên không thể định nghĩa hàm theo cách thông thường.

Giả sử hàm mới này cần tương tác với mã nguồn chính, cụ thể là đọc giá trị của một biến.

Vấn đề xảy ra ở đây là: trước khi triển khai web lên môi trường thật, mã nguồn thường được nén lại để giảm thiểu dung lượng.

Cụ thể là chương trình nén sẽ xóa bỏ dấu cách, ghi chú code và đặc biệt là đổi tên biến thành dạng ngắn gọn hơn. Ví dụ biến userName được đổi thành a chẳng hạn.

Nếu hàm tạo bởi new Function muốn đọc giá trị của biến userName thì sẽ sinh ra lỗi, vì không tìm thấy biến userName nữa.

Để đọc giá trị của biến bên ngoài với cú pháp new Function, bạn hãy truyền giá trị của biến đó vào hàm thông qua tham số.

Tổng kết

Cú pháp new Function trong JavaScript là:

let func = new Function([arg1, arg2, ...argN], functionBody);

Bạn có thể truyền tham số vào hàm theo các cách khác nhau như sau:

// cú pháp cơ bản
new Function("a", "b", "return a + b");

// các tham số cách nhau bởi dấu phẩy
new Function("a,b", "return a + b");

// các tham số cách nhau bởi dấu phẩy và có dấu cách
new Function("a , b", "return a + b");

Hàm tạo bởi new Function không tham chiếu tới môi trường nơi hàm được tạo ra, mà tham chiếu đến đối tượng global.

Vì vậy, hàm này không thể đọc được giá trị của biến ngoài hàm. Điều này là tốt vì nó giúp tránh được nhiều lỗi.

Để đọc giá trị của biến trong hàm new Function, hãy truyền giá trị của biến vào hàm thông qua tham số.

Tham khảo: The "new Function" syntax

★ Nếu bạn thấy bài viết này hay thì hãy theo dõi mình trên Facebook để nhận được thông báo khi có bài viết mới nhất nhé:

Function object trong JavaScript
Hàm setTimeout trong JavaScript
Chia sẻ:

Bình luận