2011-11-21 27 views
6

Tôi là nhà phát triển C# và được sử dụng cho cách đóng cửa hoạt động trong C#. Hiện nay tôi phải làm việc với chức năng javascript ẩn danh và gặp sự cố với đoạn mã sau:Truy cập biến số nguyên được sao chép trong phương thức ẩn danh javascript

function ClosureTest() { 
    var funcArray = new Array(); 

    var i = 0; 
    while (i < 2) { 
     var contextCopy = i; 

     funcArray[i] = function() { alert(contextCopy); return false; }; 

     i++; 
    } 

    funcArray[0](); 
    funcArray[1](); 
} 

tôi hy vọng các funcArray() cuộc gọi đầu tiên để nói 0 và giây để nói 1. Tuy nhiên, cả hai đều nói 1. Làm thế nào là có thể?

Bằng cách viết var contextCopy = i Tôi đảm bảo rằng tôi tạo bản sao của i có thể thay đổi. Sau đó, trong mỗi lần lặp lại, tôi tạo một con trỏ hàm hoàn toàn mới. Mỗi chức năng đề cập đến bản sao riêng của nó là i, là contextCopy. Tuy nhiên, cả hai hàm đã tạo vì một lý do nào đó đều tham chiếu đến cùng một số contextCopy -variable.

Cách này hoạt động trong javascript?

+0

có lý do nào bạn không sử dụng vòng lặp 'for' không? – zzzzBov

+1

không có không ;-) – TwinHabit

Trả lời

11

JavaScript có đóng cửa từ vựng, không chặn đóng. Mặc dù bạn đang gán i vào contextCopy, contextCopy là, chính nó, một thành viên từ vựng của ClosureTest (khác với C#, trong đó {} cung cấp cho bạn một khối scoped mới). Hãy thử điều này:

while (i < 2) { 
    funcArray[i] = (function(value) { 
     return function(){ alert(value); return false; } 
    })(i); 
    i++; 
} 
+0

Cảm ơn bạn, ví dụ làm việc này. Sau khi những giải thích được trình bày ở đây thì rõ ràng với tôi, tại sao lần thử đầu tiên của tôi không hoạt động. – TwinHabit

7

Niềng răng xoăn ({}) trong JavaScript không nắm bắt các biến như trong C#.

Chỉ các đóng (chức năng) mới giới thiệu phạm vi mới và nắm bắt các biến.

var i = 0; 
while (i < 2) { 
    var contextCopy = i; 
    ... 
} 

là thực sự hiểu là:

var i, contextCopy; 
i = 0; 
while (i < 2) { 
    contextCopy = i; 
    ... 
} 

Để có được một bản sao của biến, bạn sẽ cần phải bọc mã với một kết thúc:

var i; 
i = 0; 
while (i < 2) { 
    (function (contextCopy) { 
    ... 
    }(i)); 
} 
+1

+1 để chỉ ra cẩu của bối cảnh Biến bản sao (không rõ ràng như trong câu trả lời của tôi) – Matt

+0

cảm ơn bạn rất nhiều vì đã làm rõ – TwinHabit

0

Bạn không tạo một bản sao của biến i. Thay vào đó, bạn làm cho biến phụ thuộc vào GC này của các bao đóng sử dụng nó. Nó có nghĩa là khi vòng lặp while thoát ra, biến i tiếp tục sống trong trạng thái cuối cùng của nó (1) và cả hai tham chiếu đóng lại với nó. Một cách khác để đặt nó: đóng trên một biến không sao chép nó vào đóng cửa của bạn (sẽ làm cho cảm giác ít đối với các đối tượng), nó chỉ làm cho đóng của bạn tham chiếu biến và đảm bảo biến này không phải GCed cho đến khi đóng cửa được. Quay trở lại

Các vấn đề liên quan