Hi 🤓 Cảm ơn bạn đã ghé thăm blog này, nếu những bài viết trên blog giúp ích cho bạn. Bạn có thể giúp blog hiển thị quảng cáo bằng cách tạm ngừng ad blocker 😫 và để giúp blog duy trì hoạt động nếu bạn muốn.
Cảm ơn bạn!

Trong bài viết này, chúng ta cùng tìm hiểu về IIFE trong JavaScript nhé 😁.

IIFE trong JavaScript là gì?

IIFE (Immediately Invoked Function Expressions) là các hàm chạy ngay sau khi được định nghĩa.

Đầu tiên, chúng ta cùng tìm hiểu cách tạo một IIFE và một số trường hợp sử dụng nó nhé. Trong JavaScript, chúng ta có thể tạo các biểu thức với cách viết như sau:

('homiedev' + ' blog');
(10 + 20);

Chúng ta có thể bỏ qua dấu ngoặc đơn () đoạn code trên cũng chạy bình thường. Điều này thể làm tương tự với function:

(function() {});

Chúng ta đang sử dụng một anonymous function bên trong (), lúc này chưa có gì xảy ra cho đến khi thực thi nó bằng cách, sử dụng ():

               👇
(function() {})();

Để hiểu rõ hơn thì chúng ta cùng xem một ví dụ nhé:

let sum = (function(a, b) {
    return a + b;
});

Trong ví dụ này, biến sum là một anonymous function có hai đối số.

Thông thường chúng ta, có thể sử dụng biến sum và thực thi nó như sau:

let result = sum(5, 10);

console.log(result); // 15

Trong trường hợp bạn muốn thực thi ngay lập tức (Immediately Invoked) hàm trên (Function Expressions), kết quả trả từ hàm được gán vào biến sum thì chúng ta sử dụng IIFE:

// sử dụng IIFE (function(){ ... })()

let sum = (function(a,b){
    return a + b;
})(5, 10);

console.log(sum); // 15

Ở đoạn code trên, biến sum giữ kết quả của lệnh gọi hàm. Chúng ta còn có thể sử dụng arrow function để tạo một IIFE:

(() => {
    //...
})();

Đặt tên cho IIFE

Nếu bạn muốn làm cho IIFE tường minh hơn, chúng ta có thể sử dụng tên cho IIFE.

Trong ví dụ này, mình sử dụng IIFE để làm nhiệm vụ lấy dữ liệu JSON từ local, khi người khác đọc code, hoặc để sau này đọc lại có thể hiểu "cái này làm gì?" thì chúng ta có thể đặt tên cho IIFE như bên dưới:

(function getDataFromLocal() {
   fetch("./homiedev_blog_information.json")
    .then((res) => res.json())
    .then((data) => {}
})();

IIFE - Use cases

Tránh vấn đề khai báo các biến, hàm tại global namespace

Sử dụng IIFE có thể giúp chúng ta tránh việc khai báo các biến, hàm ở global object. Khi khai báo quá nhiều các biến toàn cục, hàm,... điều này có thể xảy ra vấn đề về hiệu suất hoặc bộ nhớ.

Nếu chúng ta có một số đoạn code mà không cần sử dụng lại, chúng ta có thể sử dụng IIFE thay vì sử dụng function declaration hay function expression.

(() => {
  let firstVariable;
  let secondVariable;
})();

// firstVariable và secondVariable sẽ bị loại bỏ sau khi hàm được thực thi.

Module pattern

Các biến và function trong IIFE có thể ở trạng thái private và không thể truy cập từ bên ngoài, điều này cho phép chúng ta linh hoạt tạo ra các biến, hàm có thể sử dụng tùy theo cách ta muốn.

Dưới đây là một ví dụ:

const blog = (blogName) => {
  return (function (name) {
    // các biến này là private
    let nameOfBlog = name; 
    let numberOfPosts = 0;

    const writePost = (title) => {
      console.log(
        `I'm writing new post at ${nameOfBlog} with title "${title}"`
      );
    };

    return {
      createPostWithTitle(title) {
        numberOfPosts++;
        writePost(title);
        console.log("done!");
      },

      get countPosts() {
        return numberOfPosts;
      },
    };
  })(blogName);
};

const myBlog = blog("homiedev.com");
myBlog.createPostWithTitle("Học JavaScript cơ bản - homiedev.com");
myBlog.createPostWithTitle("IIFE trong JavaScript là gì?");

console.log(myBlog.countPosts);
console.log(myBlog.numberOfPosts); // undefined
console.log(myBlog.writePost); // undefined vì method này là private

Aliasing Variables

Thỉnh thoảng, chúng ta có thể gặp phải trường hợp sử dụng hai thư viện khác nhau có sử dụng một biến toàn cục có cùng tên. Ví dụ: bạn đang sử dụng jQuery và một thư viện khác cũng sử dụng $ ở global.

Để giải quyết xung đột (conflict) đặt tên này, chúng ta có thể sử dụng IIFE để chuyển một trong các biến toàn cục (ví dụ: jQuery) làm đối số. Trong hàm này, chúng ta có thể tham chiếu đến biến jQuery bằng tên tham số (ví dụ: $) tùy các bạn chọn:

// giả sử một thư viện khác sử dụng biến toàn cục đặt là $
window.$ = function doSomething() {
  // ...
};

// sử dụng IIFE và đặt tên tham số tùy ý
// lúc này tham số của hàm sẽ là biến jQuery

(function ($) {
  // ...
})(jQuery);

Execute an async function

Thông thường, chúng ta sử dụng async / await bằng cách tạo hàm và thực thi nó như thế này:

async function getDataFromLocal() {
   const response = await fetch("./homiedev_blog_information.json");
   const data = await response.json();
   // ...
};

// gọi hàm
getDataFromLocal();

Đoạn code trên, chúng ta có thể viết ngắn lại một chút bằng cách sử dụng IIFE như sau:

(async function getDataFromLocal() {
  const response = await fetch("./homiedev_blog_information.json");
  const data = await response.json();
  // ...
})();

Trường hợp có thể thay thế IIFE

ES6 giới thiệu cho chúng ta hai từ khóa: let và const cho phép chúng ta khai báo các biến với phạm vi khối (block scope - {}). Nhờ vậy, các biến và hàm được định nghĩa bên trong một block scope chỉ có thể sử dụng được bên trong khối cụ thể đó, chúng ta có thể thay thế IIFE trong trường hợp này.

Ví dụ:

(() => {
  var form = document.querySelector('#homiedev-form');

  var handleSubmit = (e) => {};

  form.addEventListener('submit', handleSubmit);
})();

// Tại global scope: thử lấy form trong IIFE
console.log(form); // ReferenceError: form is not defined

Ở ví dụ trên, chúng ta không thể lấy và sử dụng form từ bên ngoài IIFE.

Thay thế cách trên, chúng ta có thể sử dụng let, const kết hợp với block scope ({}), điều này sẽ giúp các biến, hàm sẽ không thể sử dụng được từ bên ngoài scope.

const outside = 'homiedev.com';

// chỉ hoạt động đối với block-scope variables, ví dụ: const và let.
{
  const inside = 'Học JavaScript cơ bản';

  console.log(outside); 'homiedev.com'
  console.log(inside); 'Học JavaScript cơ bản'
 }

 console.log(outside); // 'homiedev.com'
 console.log(inside); // ReferenceError: inside is not defined

Kết luận

Như vậy là chúng ta đã tìm hiểu xong IIFE trong JavaScript là gì và một số use cases của nó trong bài viết. Hi vọng bài viết giúp ích cho các bạn.

Nếu bài viết có gì sài xót, hoặc các bạn có góp ý, thắc mắc gì thì chúng ta cùng thảo luận bên dưới phần bình luận nhé 😁.

Cảm ơn các bạn đã đọc bài viết!

Có thể bạn thích ⚡
homiedev
About Me

Hi, I'm @devnav. Một người thích chia sẻ kiến thức, đặc biệt là về Frontend 🚀. Trang web này được tạo ra nhằm giúp các bạn học Frontend hiệu quả hơn 🎉😄.

Chúc các bạn tìm được kiến thức hữu ích trong blog này 😁😁.