Javascript: Closure là cái chi chi?

Closure(bao đóng) là một khái niệm khi mà chúng ta khai báo một function trong một function khác. Khi một function được khai báo nó tạo nên một Execution Context. Với closure chúng ta có một Execution Context cha và Execution Context con. Một pattern có thể hình dung như sau:

function sum(a) {
 //parent scope, another name is lexical scope, hay outer environment của child scope
  return function(b) {
  //child scope
    return a + b;
  }
 }

Khi một pattern như vậy được khai báo thì javascript engine sẽ tạo ra một closure tại đây.

Cùng xem ví dụ sau nhé:

function sum(a) {
  return function(b) {
     return a + b;
  }
 }

let temp = sum(10);
console.log(temp(2));//12

Một ví dụ khác:

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

let arrFns = addSomeFunction();
arrFns[0]();//3
arrFns[1]();//3
arrFns[2]();//3

Chúng ta kỳ vọng kết quả là gì? Chắc có nhiều bạn cho rằng 0 1 2? Nhưng tại sao lại là 3 3 3?
Do ở đây chúng ta dùng var nên thực tế javascript chỉ cấp một vùng nhớ cho biến i. Khi chạy hết vòng for thì i này mang giá trị là 3.

Chúng ta có thể dùng let:

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

let arrFns = addSomeFunction();
arrFns[0]();//0
arrFns[1]();//1
arrFns[2]();//2

Kết quả là 0 1 2 vì let là block scope nên mỗi lần for chạy là một i khác nhau. Khác với var, ở đây mỗi lần chạy vòng for thì một vùng nhớ mới được cấp cho i. Do đó giá trị i là khác nhau.

Leave a Reply

Your email address will not be published. Required fields are marked *