Vấn đề về Closures trong javaScript

  • JavaScript
  • 25 tháng 04 2015
  • bởi Văn Khương
  • 0 Comments

Có nhiều cách diễn giải khác nhau và chúng ta cũng đã từng dùng nhưng chưa khái niệm được nó hay sự khó hiểu bởi vấn đề nó tạo ra, ở đây dựa trên sự phân tích về hàm chưa thực thi hay hàm được tạo và bối cảnh tham chiếu, có thể hiểu đơn giản như sau:

Closures Là một kỹ thuật sử dụng những hàm chưa thực thi để tham chiếu đến những giá trị bên ngoài nó khi môi trường bao nó được thực thi, có thể là một hàm sử dụng những biến của hàm cha và được hàm cha trả về hay được gán cho các đối tượng ngoài nó để thực thi sau, ví dụ điển hình sau sẽ mô tả điều này:

function myFunc(){
  var x = 1;
    function inFunc(y){
      return x + y;
  }
  return inFunc;
}
var a = myFunc();
console.log(a(10));

ý nghĩa với khái niệm này ta có các biến ở phạm vi của hàm cha vốn không được truy cập bên ngoài thì có thể được cho phép thông qua những hàm bên trong, điển hình ứng dụng điều này được thể hiện như trên mẫu modules.

Cần chú ý rằng những hàm này là những hàm chưa được thực thi hay nói cách khác là sẽ được thực thi sau bối cảnh bao nó thì mới có ý nghĩa. Chính vì điều đó cần sử dụng cẩn thận với vòng lặp, bởi vì nếu sử dụng các giá trị của từng vòng lặp cho các hàm chưa được thực thi thì đương nhiên các hàm này khi kết thúc vòng lặp sẽ đang tham chiếu đến giá trị cuối cùng của vòng lặp, cho nên các giá trị không phải là cuối của vòng lặp sẽ trở nên vô nghĩa. Ví dụ như sau:

var obj = new Object;
var x = ["red", "green", "blue"];
for(var i = 0; i < x.length; i++){
  var y = x[i];
  if(i == 0){
    obj.aAction = function(){
      return y;
    }
  }else if(i == 1){
    obj.bAction = function(){
      return y;
    }
  }
}
console.log(obj.aAction());
console.log(obj.bAction());

Kết quả trên cho thấy cả 2 phương thức của obj đều tham chiếu đến biến y và giá trị cuối cùng mà biến y nhận được sau khi kết thúc vòng lặp là "blue", để giải quyết vấn đề này ta cần thực thi ngay với bối cảnh biến y mà nó đang tham chiếu cho mỗi vòng lặp bằng cách bao nó bởi một hàm và thực thi luôn, có thể nói lúc này biến y ở mỗi bối cảnh không liên quan đến nhau ở mỗi vòng lặp. Ví dụ:

var obj = new Object;
var x = ["red", "green", "blue"];
for(var i = 0; i < x.length; i++){
  function exeMe(){
    var y = x[i];
    if(i == 0){
      obj.aAction = function(){
        return y;
      }
    }else if(i == 1){
      obj.bAction = function(){
        return y;
      }
    }
  exeMe();
}
console.log(obj.aAction());
console.log(obj.bAction());

Ngoài cách viết như hàm exeMe trên ta còn có thể viết theo kiểu hàm anonymous. Nếu bạn có cách diễn giải khác hay những minh hoạ khác hãy để lại comment bên dưới.

  • Chia sẻ
comments powered by Disqus