CodeGym /Khóa học Java /Frontend SELF VI /Đóng gói (Closure)

Đóng gói (Closure)

Frontend SELF VI
Mức độ , Bài học
Có sẵn

6.1 Khái niệm về đóng gói

Đóng gói là một trong những khái niệm mạnh mẽ và quan trọng nhất trong JavaScript. Nó cho phép các hàm ghi nhớ môi trường từ vựng của mình ngay cả sau khi chúng đã hoàn thành. Trong bài giảng này, chúng ta sẽ xem xét khái niệm đóng gói, những đặc điểm của chúng và đưa ra nhiều ví dụ về cách sử dụng chúng.

Đóng gói (closure) trong JavaScript — là sự kết hợp giữa một hàm và môi trường từ vựng, nơi mà hàm đó được khai báo. Đóng gói cho phép hàm "ghi nhớ" và truy cập vào các biến và các hàm khác từ phạm vi bên ngoài của nó, ngay cả sau khi hàm bên ngoài đó đã hoàn thành.

Những đặc điểm chính của đóng gói:

  1. Môi trường từ vựng: ngữ cảnh nơi hàm được khai báo, bao gồm tất cả các biến có sẵn tại thời điểm khai báo.
  2. Lưu trữ ngữ cảnh: hàm với đóng gói có thể giữ quyền truy cập vào các biến từ phạm vi bên ngoài của nó ngay cả sau khi hàm bên ngoài đã hoàn thành.

6.2 Ví dụ về hoạt động của đóng gói

Ví dụ 1: Đóng gói đơn giản

Trong ví dụ này, innerFunction() có quyền truy cập vào biến outerVariable từ phạm vi bên ngoài của nó ngay cả sau khi outerFunction() hoàn thành.

JavaScript
    
      function outerFunction() {
        let outerVariable = 'I am from the outer function';

        function innerFunction() {
          console.log(outerVariable);
        }
        return innerFunction;
      }

      const closure = outerFunction();
      closure(); // Sẽ hiển thị: I am from the outer function
    
  

Ví dụ 2: Bộ đếm sử dụng đóng gói

Trong ví dụ này, hàm bộ đếm lưu trữ giá trị của biến count và tăng nó mỗi khi được gọi.

JavaScript
    
      function createCounter() {
        let count = 0;

        return function() {
          count++;
          return count;
        };
      }

      const counter = createCounter();

      console.log(counter()); // Sẽ hiển thị: 1
      console.log(counter()); // Sẽ hiển thị: 2
      console.log(counter()); // Sẽ hiển thị: 3
    
  

Ví dụ 3: Đóng gói trong vòng lặp

Đóng gói thường được sử dụng để lưu giữ giá trị của các biến trong vòng lặp.

Trong ví dụ này, mỗi hàm bên trong mảng arr "ghi nhớ" giá trị của biến i tại thời điểm nó được tạo ra nhờ vào phạm vi khối của let:

JavaScript
    
      function createArrayWithClosures() {
        let arr = [];

        for (let i = 0; i < 3; i++) {
          arr[i] = function() {
            console.log(i);
          };
        }
        return arr;
      }

      const closures = createArrayWithClosures();

      closures[0](); // Sẽ hiển thị: 0
      closures[1](); // Sẽ hiển thị: 1
      closures[2](); // Sẽ hiển thị: 2
    
  

6.3 Các kịch bản phức tạp của việc sử dụng đóng gói

Ví dụ 1: Áp dụng hàm một phần (partial application)

Đóng gói cho phép tạo ra các hàm được áp dụng một phần, giữ một số đối số cố định.

Trong ví dụ này, hàm multiply() trả về một hàm, hàm này nhân đối số b mà nó nhận với đối số a đã được cố định.

JavaScript
    
      function multiply(a) {
        return function(b) {
          return a * b;
        };
      }

      const double = multiply(2);
      console.log(double(5)); // Sẽ hiển thị: 10
      console.log(double(10)); // Sẽ hiển thị: 20
    
  

Ví dụ 2: Giấu dữ liệu (data hiding)

Đóng gói có thể được sử dụng để tạo ra các biến và phương thức riêng tư.

Trong ví dụ này, các biến _name_age là riêng tư và chỉ có thể truy cập thông qua các phương thức đối tượng:

JavaScript
    
      function createPerson(name, age) {
        let _name = name;
        let _age = age;

        return {
          getName: function() {
            return _name;
          },
          getAge: function() {
            return _age;
          },
          setName: function(newName) {
            _name = newName;
          },
          setAge: function(newAge) {
            _age = newAge;
          }
        };
      }

      const person = createPerson('John', 30);
      console.log(person.getName()); // Sẽ hiển thị: John

      person.setName('Jane');

      console.log(person.getName()); // Sẽ hiển thị: Jane
      console.log(person.getAge());  // Sẽ hiển thị: 30
    
  

Ví dụ 3: Memoization

Memoization — là kỹ thuật tối ưu hóa, trong đó kết quả của hàm được lưu trữ để tránh việc tính toán lại nhiều lần cho cùng một dữ liệu đầu vào.

Trong ví dụ này, hàm memoize() sử dụng đóng gói để lưu trữ cache của các kết quả đã được tính toán của hàm fn():

JavaScript
    
      function memoize(fn) {
        const cache = {};

        return function(...args) {
          const key = JSON.stringify(args);
          if (cache[key]) {
            return cache[key];
          }
          const result = fn(...args);
          cache[key] = result;
          return result;
        };
      }

      function slowFunction(num) {
        console.log('Computing...');
        return num * 2;
      }

      const memoizedFunction = memoize(slowFunction);

      console.log(memoizedFunction(5)); // Sẽ hiển thị: Computing... 10
      console.log(memoizedFunction(5)); // Sẽ hiển thị: 10 (kết quả lấy từ cache)
    
  
1
Опрос
Date, Timer và literals,  37 уровень,  5 лекция
недоступен
Date, Timer và literals
Date, Timer và literals
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION