2012-06-08 24 views
8

Giả sử tôi có một chức năng một:Làm thế nào để vượt qua "này" để cửa sổ setInterval

function a() { 
    this.b = 1; 
    this.set = setInterval(function() {console.log(this.b);}, 200); 
} 

Vì vậy, khi a.set() được gọi là chức năng ẩn danh sẽ được gọi. Nhưng điều này sẽ không hoạt động như lúc này khi hàm được kích hoạt trỏ tới đối tượng cửa sổ. Ngoài ra, không nên sử dụng a.b vì có thể có nhiều phiên bản của a.

Giải pháp tốt cho vấn đề này là gì?

+0

tại sao bạn không sử dụng 'apply' hoặc' call' https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/apply – Deeptechtons

+0

@Deeptechtons - Tôi không nghĩ rằng 'apply' hoặc 'gọi' là bất kỳ sử dụng cho vấn đề này, nhưng có lẽ bạn có thể giải thích những gì bạn đã có trong tâm trí trong một câu trả lời? – nnnnnn

+0

@nnnnnn Câu hỏi chắc chắn là một ứng cử viên cho "Làm thế nào để tôi thay đổi bối cảnh bên trong chức năng" loại câu hỏi. Mà được giải quyết bằng cách sử dụng appy, hoặc gọi. Nhưng có thể là quá mức cần thiết cho trường hợp này. – Deeptechtons

Trả lời

16

Lưu trữ một tham chiếu đến this:

function a() { 
    var self = this; 
    self.b = 1; 
    self.set = setInterval(function() {console.log(self.b);}, 200); 
} 

Chức năng vô danh mà bạn vượt qua để setInterval có quyền truy cập vào bất kỳ biến trong phạm vi chứa nó, nghĩa là, bất kỳ biến địa phương của function a(). Sự kỳ diệu của việc đóng cửa JS giữ cho các biến này còn sống ngay cả sau khi a() đã hoàn thành và mỗi yêu cầu a() bị đóng cửa riêng.

+0

Yea Tôi đã nhìn thấy những ví dụ như thế nhưng đó chính là điều làm tôi bối rối. Giả sử "a" kết thúc trước khi sự kiện tại 200ms được kích hoạt, biến tự dường như là nó sẽ bị phá hủy tại thời điểm đó. Nếu không, sau đó khi nó sẽ bị phá hủy? sau khi khoảng thời gian được xóa? – NSF

+0

Như tôi đã đề cập trong câu trả lời của tôi, một hàm bên trong có quyền truy cập vào các biến trong phạm vi hàm chứa của nó _even sau khi hàm contains_ đã hoàn thành. Trong trường hợp này 'setInterval' tiếp tục giữ một tham chiếu đến hàm bên trong để nó có thể tiếp tục gọi nó ngay cả sau khi' a() 'đã kết thúc; cho đến khi khoảng thời gian được xóa, tham chiếu đó sẽ vẫn còn sống và các biến sẽ vẫn còn sống. Lưu ý rằng 'a()' sẽ _definitely_ kết thúc trước khi khoảng thời gian được kích hoạt (bất kể khoảng thời gian ngắn như thế nào) bởi vì JS chạy trên một chuỗi đơn. "Đóng JavaScript" của Google để biết thêm thông tin. – nnnnnn

+0

có ý nghĩa. Cảm ơn. – NSF

2

Chỉ cần lưu this tài liệu tham khảo của bạn trong một số biến khác, đó không phải là ghi đè bởi các window -call sau này. Sau đó, bạn có thể sử dụng biến đó để tham chiếu đến đối tượng mà bạn đã bắt đầu.

function a() { 
    this.b = 1; 
    var that = this; 
    this.set = setInterval(function() {console.log(that.b);}, 200); 
} 
0

Trong trường hợp của bạn, bạn có thể chỉ đơn giản là:

function a() { 
    var _this = this; 
    this.b = 1; 
    this.set = setInterval(function() { 
     console.log(_this.b); 
    }, 200); 
} 

Thông thường, chúng ta cũng có thể có một phương pháp helper Function.prototype.bind để sửa chữa các this tham khảo.

4

này sẽ là giải pháp sạch nhất, vì hầu hết thời gian bạn thực sự muốn chuyển sang bối cảnh này cho phương pháp liên tiếp của bạn gọi:

// store scope reference for our delegating method 
    var that = this; 
    setInterval(function() { 
     // this would be changed here because of method scope, 
     // but we still have a reference to that 
     OURMETHODNAME.call(that); 
    }, 200); 
3

Kể từ khi chúng tôi có ES6 bây giờ, tôi nghĩ rằng chúng ta cần câu trả lời khác ở đây :

Sử dụng chức năng mũi tên:

function a() { 
    this.b = 1; 
    this.set = setInterval(() => {console.log(this.b);}, 200); 
} 

chức năng mũi tên, đối diện với các chức năng bình thường, không có một bối cảnh this trên của họ sở hữu. Điều này có nghĩa là bạn có quyền truy cập vào bên ngoài this.

+1

ES6 đã giảm cú pháp của tôi hầu như không có gì, một lần nữa! Cảm ơn! – HoldOffHunger

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