:quality(75)/2024_2_20_638440211025685967_closure-la-gi-1-1.jpg)
Closure là gì? Cập nhật các hàm Closures lưu trữ biến số và cách ứng dụng thực tế hiệu quả
Closure là gì? Khái niệm này thường được quan tâm bởi những người hoạt động trong ngành công nghệ thông tin. Nhờ vào cách áp dụng Closure hiệu quả sẽ giúp Developer nâng cao cơ hội nghề nghiệp của mình. Hãy cùng FPT Shop theo dõi về chủ đề này thông qua bài viết dưới đây nhé!
Một số kiến thức cơ bản về hàm Closure
Closure là gì?
Thuật ngữ "closure" thường được sử dụng để mô tả một khái niệm cơ bản trong ngôn ngữ lập trình hàm (function). Closure xảy ra khi hàm được tạo ra dưới dạng biến bên trong một hàm khác. Đồng thời, hàm con đó vẫn có thể truy cập được các biến của hàm bên ngoài trong khi hàm bên ngoài đã thực thi xong.

Với cách giải thích khác, khi hàm bên trong được tạo ra và sử dụng một biến từ phạm vi bên ngoài của nó, nó sẽ tạo ra một Closure. Closure cho phép hàm bên trong "ghi nhớ" trạng thái của biến bên ngoài vào thời điểm nó được tạo. Sau đó, hàm bên trong có thể sử dụng các giá trị này ngay cả khi hàm bên ngoài đã kết thúc quá trình thực thi.
Đây là một nguyên tắc vô cùng hữu ích trong việc lập trình, đặc biệt với các ngôn ngữ hỗ trợ first - class functions như JavaScript, Python và Ruby. Nơi Closure sẽ được tạo ra và sử dụng một cách linh hoạt để giải quyết nhiều vấn đề khác nhau.
Hàm Closures có khả năng truy cập biến số ở 3 phạm vi khác nhau như sau:
- Biến dạng toàn cục.
- Biến đã được khai báo ở hàm số có chứa sẵn hàm Closures (outer function)
- Biến nằm ở trên hoặc trong hàm Closures
Cách nhận diện Closure như thế nào?
Closure đã trở thành khái niệm mô tả mối quan hệ giữa hàm và môi trường biến xung quanh nó trong quá trình thực thi.

Khi một hàm được tạo bên trong một hàm khác và sau đó truy cập các biến của hàm bên ngoài sẽ tạo ra một Closure. Closure không có hình dạng hay cách nhận biết cụ thể mà chúng chỉ tồn tại trong quá trình thực thi của chương trình.
Chúng ta có thể nhận diện Closure thông qua việc tạo và sử dụng function init. Chẳng hạn như ví dụ dưới đây:
closure function init() { var name = "Closure"; function hi() { console.log('my name is ' + name); } return hi; // lưu ý không viết là return hi() } var f = init(); f();
Trong ví dụ này, khi function init được gọi, nó tạo ra biến name và function hi, sau đó trả về function hi. Khi f được gán bằng init(), nó thực chất sở hữu Closure của init, bao gồm biến name và function hi được lưu trữ trong môi trường của nó. Khi f được gọi, nó vẫn có thể truy cập được biến name từ môi trường ban đầu của init cho thấy sự tồn tại và sử dụng của Closure.
Việc sử dụng phần mềm như Chrome Developer Tools để xem rõ các scope và environment cũng có thể giúp nhận diện Closure trong JavaScript bằng cách theo dõi các biến và function được lưu trữ cùng với hàm gọi.
Quá trình nhận diện Closure trong JavaScript được áp dụng bằng cách theo dõi và hiểu rõ môi trường thực thi cũng như sự tương tác giữa hàm, biến trong quá trình thực thi.
Closures lưu trữ biến số của Outer Function theo dạng tham chiếu
Trong lập trình, Closures có mối quan hệ mật thiết với các ngôn ngữ như JavaScript và Python. Closures cho phép hàm con (inner function) trong một hàm khác (outer function) truy cập và sử dụng các biến của outer function, ngay cả khi outer function đã thực thi xong.

Trong trường hợp biến trong outer function được sử dụng bởi inner function, chúng được lưu trữ theo dạng tham chiếu (reference) trong Closure. Điều này có nghĩa là nó vẫn liên kết với vùng nhớ của biến gốc, không phải làm một bản sao (copy).
Khi outer function thực thi và trả về inner function, Closure bao gồm tất cả các biến mà inner function sử dụng từ outer function, kể cả sau khi outer function đã kết thúc. Điều này cho phép chúng ta tận dụng các giá trị và trạng thái của outer function trong nhiều ngữ cảnh khác nhau. Từ đó tạo ra các hàm linh hoạt và mạnh mẽ.
Đây là một ví dụ trong JavaScript:
javascript
function outerFunction() {
var outerVariable = 'I am from the outer function';
function innerFunction() {
console.log(outerVariable);
}
return innerFunction;
}
var closure = outerFunction();
closure(); // Output: I am from the outer function
Trong ví dụ này, inner function vẫn có thể truy cập và sử dụng outerVariable ngay cả khi outer function đã kết thúc, nhờ vào Closure lưu trữ biến theo dạng tham chiếu.
Những ứng dụng thực tế của Closure
Closure thường được sử dụng trong nhiều ứng dụng thực tế trong lập trình. Dưới đây là một vài ví dụ cụ thể về cách sử dụng của Closure:

Bảo mật dữ liệu
Closure thường được sử dụng để bảo vệ dữ liệu trong JavaScript. Bằng cách sử dụng Closure để bao bọc dữ liệu và chỉ expose các phương thức để truy cập và thay đổi dữ liệu mà chúng ta hoàn toàn có thể kiểm soát quyền truy cập, bảo mật thông tin quan trọng.
Giao tiếp với APIs và xử lý bất đồng bộ
Trong lập trình JavaScript, Closure còn được sử dụng để tạo các hàm callback hoặc xử lý promise trong việc giao tiếp với các APIs. Nó được dùng để xử lý các tác vụ bất đồng bộ. Điều này giúp chúng ta tạo ra mã linh hoạt và dễ bảo trì hơn.
Hiển thị thông tin trong giao diện người dùng (UI)
Closure được áp dụng trong việc tạo các hàm xử lý sự kiện và tương tác với giao diện người dùng. Việc sử dụng Closure giúp lưu trữ trạng thái và dữ liệu cục bộ trong quá trình tương tác với người dùng một cách hiệu quả.

Cache và quản lý trạng thái
Nhờ vào những tiện ích đặc biệt mà Closure còn được sử dụng để tạo các hàm có khả năng cache kết quả, giúp tối ưu hóa hiệu suất của ứng dụng. Ngoài ra, Closure cũng có khả năng quản lý trạng thái của ứng dụng, giúp duy trì dữ liệu và trạng thái trong quá trình thực thi.
Module pattern trong JavaScript
Cuối cùng, Closure thường được áp dụng để tạo các module JavaScript nhằm tạo ra phạm vi và bảo vệ dữ liệu trong ứng dụng. Điều này giúp hệ thống tổ chức mã nguồn một cách có cấu trúc và bảo mật toàn diện, ngăn chặn việc xâm nhập và xung đột giữa các thành phần khác nhau trong ứng dụng.
Những ứng dụng trên chỉ là một số ít các lợi ích mà người dùng có thể nhận được khi ứng dụng Closure trong thực tế. Từ sự linh hoạt và mạnh mẽ mà nó đã trở thành một công cụ quan trọng, thú vị trong việc xây dựng hoặc thiết kế ứng dụng lập trình.
Ví dụ về các trường hợp sử dụng Closure
Trường hợp 1: Function factory
Những trường hợp sử dụng Closure thực tế trong Function factory diễn ra rất phổ biến. Chẳng hạn với function factory là một pattern trong lập trình chức năng, nơi mà hàm được sử dụng để tạo và trả về các hàm khác dựa trên các đối số hoặc điều kiện đầu vào.

Khi sử dụng Closure, function factory có thể tạo ra các hàm con chứa thông tin từ môi trường của function factory. Điều này có tác dụng tạo ra các hàm con có trạng thái và hành vi độc lập.
Để minh họa hoạt động trên, chúng ta có thể xem xét một ví dụ về việc sử dụng JavaScript:
javascript
function makeMultiplier(x) {
return function(y) {
return x * y;
};
}
var multiplyBy2 = makeMultiplier(2);
var multiplyBy3 = makeMultiplier(3);
console.log(multiplyBy2(5)); // Output: 10
console.log(multiplyBy3(5)); // Output: 15
Trong ví dụ này, makeMultiplier là một function factory. Nó nhận một đối số x, và trả về một hàm con có thể nhận đối số y và trả về tích của x và y. Khi makeMultiplier(2) được gọi, nó trả về một hàm thực hiện việc nhân với 2. Tương tự, make Multiplier(3) trả về một hàm nhân với 3.
Điều đặc biệt ở đây là các hàm con trả về từ make Multiplier sử dụng closure để lưu trữ giá trị của x, mặc dù make Multiplier đã kết thúc thực thi. Điều này cho phép chúng ta sử dụng các hàm con (multiply By 2 và multiply By 3) với các giá trị x khác nhau mà không cần phải lưu trữ x trong mỗi hàm con.
Qua ví dụ này, chúng ta đã thấy rõ sự mạnh mẽ của Closure trong trường hợp function factory. Tiện ích giúp tạo ra các hàm con linh hoạt và tái sử dụng được, mỗi hàm con có thể có trạng thái và hành vi độc lập dựa trên biến của function factory sử dụng Closure của chúng.
Trường hợp 2: Mô phỏng lại phạm vi của biến trong OOP (variable visibility)
Trong lập trình hướng đối tượng (OOP), việc quản lý phạm vi của biến cũng được gọi là variable visibility. Đây là một yếu tố quan trọng trong việc xây dựng ứng dụng chất lượng và dễ bảo trì.

Đối với ngôn ngữ không hỗ trợ trực tiếp cấu trúc phạm vi như JavaScript, việc sử dụng Closure có tác dụng mô phỏng lại phạm vi của biến trong OOP.
Dưới đây là một ví dụ cụ thể về cách sử dụng Closure để mô phỏng lại phạm vi của biến trong OOP bằng JavaScript:
javascript
function createCounter() {
let count = 0; // Biến count chỉ có thể được truy cập bên trong function createCounter
return {
increase: function() {
count++; // Phạm vi của biến count được duy trì và sử dụng bởi hàm increase thông qua closure
},
getCount: function() {
return count; // Hàm getCount cũng có thể truy cập và trả về giá trị của biến count thông qua closure
}
};
}
const counter = createCounter();
counter.increase();
counter.increase();
console.log(counter.getCount()); // Output: 2
Trong ví dụ trên, hàm createCounter tạo ra và trả về một object chứa hai phương thức increase và getCount. Biến count là một biến private chỉ có thể được truy cập bên trong function create Counter. Nhờ vào Closure, các phương thức increase và getCount vẫn có thể truy cập và thao tác với biến count mặc dù đã ra khỏi phạm vi của function create Counter.
Điều này tương tự như cách mà các ngôn ngữ OOP khác như Java hoặc C# quản lý phạm vi của biến trong các lớp và đối tượng. Sử dụng Closure giúp mô phỏng lại tính chất này trong JavaScript hoặc các ngôn ngữ không hỗ trợ phạm vi biến một cách trực tiếp. Như vậy, Closure có thể được sử dụng để mô phỏng phạm vi của biến trong OOP, giúp tạo ra các hàm và đối tượng có tính bao đóng và bảo mật.
Tạm kết
FPT Shop đã giúp bạn đọc giải đáp câu hỏi Closure là gì và cập nhật rất nhiều kiến thức thú vị xoay quanh chủ đề này. Hy vọng bạn có thể hiểu và áp dụng hàm trong quá trình làm việc với JavaScript thật hiệu quả.
Xem thêm:
- Khám phá nguyên lý hoạt động của Hitbox, cách thiết kế trong game vô cùng hiệu quả
- Ponzi là gì? Mách bạn cách nhận biết mô hình đa cấp Ponzi nhanh chóng và chuẩn xác
FPT Shop mang đến rất nhiều loại thiết bị công nghệ chính hãng và chất lượng uy tín nổi tiếng trên toàn quốc. Khi bạn ghé thăm cửa hàng hoặc theo dõi trang chủ sẽ được lựa chọn nhiều sản phẩm giá tốt với chính sách ưu đãi đặc biệt.
:quality(75)/estore-v2/img/fptshop-logo.png)
:quality(75)/2022_11_24_638048624259742642_javascript-la-gi-2.png)
:quality(75)/2023_12_6_638374545840302567_sentry-la-gi-1-1.jpg)
:quality(75)/2024_2_1_638424203547654643_javascript-framework.jpg)
:quality(75)/2020_2_20_637178048748204339_macos-1.jpg)
:quality(75)/2024_1_18_638411663140775429_eslint-la-gi-1-1.jpg)