Hướng dẫn dùng clpsure JavaScript

Trong bài này chúng ta sẽ tìm hiểu hàm closure trong javascript, đây là một cách tạo hàm khá hay mà chắc hẳn các bạn đã gặp rất nhiều trong quá trình làm việc với javascript.

Nội dung chính

  • 1. Closure javascript là gì?
  • 2. Closure trong javascript với biến của hàm cha
  • 3. Con trỏ this trong closure function
  • 4. Closure trong class javascript
  • 5. Một vài ví dụ về closure trong javascript
  • Closure có tham số
  • Return nhiều closure function
  • Closure thay đổi giá trị biến toàn cục lẫn cục bộ
  • 6. Độ ưu tiên các biến trong closure function
  • 7. Lời kết

Nội dung chính

  • 1. Closure javascript là gì?
  • 2. Closure trong javascript với biến của hàm cha
  • 3. Con trỏ this trong closure function
  • 4. Closure trong class javascript
  • 5. Một vài ví dụ về closure trong javascript
  • Closure có tham số
  • Return nhiều closure function
  • Closure thay đổi giá trị biến toàn cục lẫn cục bộ
  • 6. Độ ưu tiên các biến trong closure function
  • 7. Lời kết

Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

Closure function là một khái niệm không phải ai cũng biết và thực sự hiểu về nó. Đây được xem là một cách định nghĩa hàm giúp code nhìn trong sáng và sử dụng linh hoạt hơn. Vì vậy, nếu bạn muốn học javascript nâng cao hoặc học các framework khác thì phải hiểu về closure.

Vậy closure là gì? Cách tạo closure như thế nào? Khi nào thì sử dụng hàm closure? Chúng ta cùng tìm hiểu ngay nhé.

1. Closure javascript là gì?

Closure là một hàm được tạo ra từ bên trong một hàm khác, nó có thể sử dụng các biến toàn cục, biến cục bộ của hàm cha và biến cục bộ của chính nó. Việc viết hàm theo kiểu closure trong một số trường hợp sẽ giúp code nhìn sáng và dễ quản lý hơn, linh hoạt hơn trong một số trường hợp.

Bài viết này được đăng tại [free tuts .net]

Để hiểu được hàm closure trong javascript thì bạn phải hiểu được khái niệm về phạm vi của một biến scope. Scope là phạm vi của biến, nơi mà biến tồn tại, hay nói chính xác hơn đó là nơi mà biến sinh ra và chết đi, và chỉ những chương trình nằm trong phạm vi đó mới sử dụng được biến.

Khi bạn tạo một biến trong một hàm, thì phạm vi hoạt động của biến đó chỉ ở bên trong hàm đó mà thôi. Sau khi gọi xong thì biến sẽ bị hủy, và như vậy là kết thúc một vòng đời.

Khi khai báo biến với từ khóa var thì phạm vi của nó rộng hơn rất nhiều so với từ khóa let. Biên let chỉ tồn tại trong phạm vi bắt đầu bằng { và kết thúc bằng } [ta hay gọi là block scoped], tức mức hoạt động cao nhất của nó là cục bộ. Còn biến var thì khác, nó có thể là biến toàn cục hoặc cục bộ.

Bạn có thể tham khảo bài viết từ khóa let trong javascript để hiểu rõ hơn về nó.

Quay trở lại vấn đề chính của bài viết này, đó là closure trong js. Theo khái niệm của nó thì chúng ta chỉ việc tạo một hàm nằm bên trong một hàm khác thì đó chính là closure.

Ví dụ dưới đây mình tạo một hàm sayHi[]:

function sayHi[name]{
    let say = function[]{
        alert["Xin chào, tôi là " + name];
    };
    return say;
}

Trong ví dụ này thì hàm say[] chính là một closure function. Bên trong nó có thể sử dụng được biến của hàm cha name.

Bạn cũng có thể return về luôn thay vì đặt tên cho hàm closure đó.

function sayHi[name]{
    return function[]{
        alert["Xin chào, tôi là " + name];
    };
}

Bây giờ mình sẽ gọi đến hàm sayHi, và gán nó vào biến tên là cuong. Sau đó mình log biến cuong này xem nó là gì nhé.

var cuong = sayHi["Cường"];
console.log[cuong];

Kết quả trả vè nó là một function như sau:

Lý do khá đơn giản, bởi vì trong hàm sayHi mình return về một function, vì vậy biến cuong chính là function mà mình đã return đó. Để in ra thông báo thì chúng ta phải gọi kích hoạt function này.

var cuong = sayHi["Cường"];
cuong[]; // Kết quả: Xin chào, tôi là cường

Như vậy là bạn đã hiểu hàm closure trong javascript rồi phải không nào? Bây giờ mình sẽ đi tiếp phần 2 để nói về cách sử dụng biến cha trong closure function.

2. Closure trong javascript với biến của hàm cha

Trước khi đi vào vấn đề chính thì mình xin nhắc lại hai lưu ý sau:

  • Các biến bên trong hàm sẽ kết thúc khi hàm đó được chạy xong.
  • Closure có thẻ sử dụng biến cục bộ, biến hàm cha và biến trong chính hàm đó.

Bây giờ hãy tạo cho mình một function như sau:

function counter[]{
    var count = 1;
    return function[]{
        return count++;
    };
}

Hàm counter trả về một closure function, function đó có nhiệm vụ là tăng biến counter lên 1 đơn vị và trả kết quả về.

Mình sẽ gọi đến hàm counter như sau:

Nếu theo quy tắc trên thì hàm counter[] đã được chạy xong, và biến count bên trong hàm này đương nhiên là sẽ bị hủy. Tuy nhiên, nó vẫn còn tồn tại bên trong closure function nhé các bạn, bằng cách thực thi hàm c[] thì ta sẽ nhận được giá trị của biến count.

var c = counter[];
console.log[c[]]; // Kết quả: 1

Mình sẽ gọi hàm c[] thêm vài lần nữa.

var c = counter[];
console.log[c[]]; // Kết quả: 1
console.log[c[]]; // Kết quả: 2
console.log[c[]]; // Kết quả: 3
console.log[c[]]; // Kết quả: 4

Vậy, hàm closure có thể sử dụng các biến của hàm cha mặc dù hàm cha đã chạy xong.

3. Con trỏ this trong closure function

Cũng như những function khác, nếu bạn đang chạy chế độ strict mode thì con trỏ this sẽ là undefined, còn không thì nó là đối tượng window.

Chế độ bình thường

function sayHi[]{
    return function[]{
        console.log[this];
    };
}

var msg = sayHi[];
msg[]; // window object

Chế độ strict mode

'use strict';
function sayHi[]{
    return function[]{
        console.log[this];
    };
}

var msg = sayHi[];
msg[]; // Undefined

4. Closure trong class javascript

Bạn có thể tạo một closure trong các phương thức của class. Tuy nhiên, vì this trong closure là undefined nên bạn không thể truy cập đến các thuộc tính của class.

Có một mẹo khá đơn giản, đó là bạn tạo một biến và gán nó chính bằng con trỏ this ở trong các phương thức của classs.

class Student{
    constructor[name]{
        this.name = name;
    }
    
    showName[]{
        // Đặt một cái tên khác cho this
        let obj = this;
        return function[]{
            console.log["Xin chào, tôi là " + obj.name];
        };
    }
}

var student1 = new Student["Cường"];
var cuong = student1.showName[];
cuong[];

5. Một vài ví dụ về closure trong javascript

Tới đây thì chắc hẳn các bạn đã hiểu được khái niệm closure javascript là gì rồi phải không nào? Bây giờ ta sẽ thực hành thông qua một vài ví dụ, mỗi ví dụ là một trường hợp mà chắc chắn sau này bạn sẽ gặp khi làm việc với javascript.

Closure có tham số

Trong ví dụ các phần trên trên mình tạo một closure không có tham số. Vậy nếu trường hợp có tham số thì cách viết như thế nào? Bạn xem ví dụ dưới đây sẽ hiểu.

// Bước 1: Tạo hàm closure
function showMessage[message]
{
    return function[time]{
        for [var i = 1; i 

Chủ Đề