+5

Scope và Closure trong Javascript

** 1. Scope là gì**

Phạm vi có thể sử dụng được các variable tùy ý.

  • Global scope: Đúng với tên gọi nó mang nghĩa toàn cầu, có thể truy cập từ bất cứ nơi đâu trên toàn program.
  • Local scope: Chỉ có thể truy cập được từ một phạm vi nhất định.
  • Về cơ bản trong function sẽ là local scope.
  • Variable được tạo ra trong function (local scope) chỉ có thể được tham chiếu trong đó.
  • Argument của function cũng chỉ có thể được tham chiếu ở phạm vi phía bên trong của function.

Ví dụ 1:

function myfunc(){
    var name = "Gyu-Ri";
}
my func();
alert(name); // ReferenceError

Do name là local variable cho nên không thể tham chiếu biến này từ bên ngoài -> gây lỗi Reference Error.

Ví dụ 2:

var a = 123;
function func1(){
    var b = 3;
    function func2(){
        var c = 2;
        alert(a * b * c); //738
    }
    func2();
}
func1();

Tại chỗ gọi alert, ta có thể sử dụng được cả biến ở phía ngoài func2().

  • Mấu chốt: Scope của Javascript chỉ có thể nhìn từ trong ra ngoài, không thể nhìn từ ngoài vào trong.

Ví dụ 3:

var name = "Nicole";
function myfunc(){
    var name = "Gyu-Ri";
}
myfunc();
alert(name); // Nicole

Ở ví dụ trên có 2 chỗ định nghĩa biến name, tuy nhiên do scope khác nhau nên ta sẽ tạo được 2 biến khác nhau.

Cũng chính vì lý do này nên khi ta gọi alert ở phía dưới, kết quả trả về của alert sẽ là biến name ở ngoài, không liên quan đến việc set giá trị biến name trong hàm myfunc.

Nếu như thế, trường hợp sau đây kết quả sẽ là gì: Ví dụ 4:

var name = "Nicole";
function myfunc(){
    name = "Gyu-Ri";
}
myfunc();
alert(name); //???

Trong trường hợp này, kết quả trả về của alert sẽ là Gyu-Ri do biến name được set giá trị trong hàm myfunc chính là biến name đã được định nghĩa ở ngoài.

Từ đây chúng ta có thể nhìn ra điểm khác nhau giữa 2 ví dụ, điều gây ra ảnh hưởng đến kết quả chính là sự có mặt của var hay không.

  • Ý nghĩa của var chính là tuyên bố định nghĩa một variable mới.
var a = 123

Để tạo ra một variable mới, nhất quyết phải có var ở phía trước.

Từ đây ta có thể suy ra rằng, nếu không sử dụng var sẽ có ý nghĩa là biến số này đã tồn tại và hãy sử dụng nó.

Hãy nhìn lại về ví dụ 2 ở phía trên.

Ở local scope được tạo ra bởi hàm func2 chỉ có duy nhất biến c là định nghĩa mới, a và b đều được hiểu là đã tồn tại. Khi không thể tìm thấy biến a và b ở trong local scope của func2, javascript sẽ tự động tìm đến local scope của func1 bên ngoài, và trong trường hợp này sẽ tìm thấy biến b. Tương tự như vậy, javascript sẽ tiếp tục tìm tại local scope bên ngoài của func1 và sẽ dừng lại khi đã đến global scope, tại đây, ta tìm thấy nốt biến a còn lại.

Đây chính là cách hoạt động của javascript, tìm kiếm lần lượt từ trong ra ngoài cho đến khi gặp global scope.

** 2. Closure là gì**

Các biến số (không phải là argument của hàm) sẽ không phụ thuộc vào môi trường đang được chạy, mà phụ thuộc vào môi trường mà nó được định nghĩa (scope tĩnh).

Có nghĩa là:

Hàm func2 trong ví dụ 2, môi trường mà nó được định nghĩa là tất cả các scope bao gồm hàm này.

Ứng dụng của closure:

  • Giấu variable, sử dụng tên khác.

Ví dụ 5:

var Person = (function($){
    var privateValue = "Hogeta";

    function Person(name){...}
    Person.prototype.xxx = ...

    return Person;
})(jQuery);
  • Argument $: Bằng cách sử dụng argument, có thể sử dụng tên khác của object
  • Biến privateValue không thể tham chiếu được từ bên ngoài nên có thể hiểu là đang được ẩn giấu.
  • jQuery được bọc bởi self-executing anonymous function, tạo ra một local scope.

Tại đây, phía bên ngoài của self-executing anonymous function không thể tham chiếu được biến privateValue và $, tuy nhiên những hàm được định nghĩa ở phía bên trong của scope này thì có thể.

Self-executing anonymous function có ý nghĩa là hàm không tên và được chạy (execute) ngay lập tức rồi kết thúc. Tuy nhiên những biến privateValue và $ của nó vẫn tiếp tục được tham chiếu bởi những hàm định nghĩa ở phía trong scope này.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí