2009-04-02 38 views
25

Hành vi của "này" khi chức năng bar được gọi là gây bối rối cho tôi. Xem mã bên dưới. Có cách nào để sắp xếp cho "này" là một trường hợp đối tượng js cũ đồng bằng khi thanh được gọi từ một trình xử lý nhấp chuột, thay vì là phần tử html?jQuery/JavaScript "này" con trỏ nhầm lẫn

// a class with a method 

function foo() { 

    this.bar(); // when called here, "this" is the foo instance 

    var barf = this.bar; 
    barf(); // when called here, "this" is the global object 

    // when called from a click, "this" is the html element 
    $("#thing").after($("<div>click me</div>").click(barf)); 
} 

foo.prototype.bar = function() { 
    alert(this); 
} 
+0

Vui lòng giải thích '" đây là trường hợp foo'. Các jsfiddle sau (http://jsfiddle.net/yY6fp/1/) chứng minh rằng 'this' trong' this.bar() 'đánh giá đối tượng' window' (global). –

Trả lời

33

Chào mừng bạn đến với thế giới của javascript! : D

Bạn đã đi lang thang vào lĩnh vực phạm vi javascript và đóng.

Đối với câu trả lời ngắn:

this.bar() 

được thực hiện thuộc phạm vi foo, (như này đề cập đến foo)

var barf = this.bar; 
barf(); 

được thực hiện dưới sự phạm vi toàn cầu.

this.bar về cơ bản có nghĩa là:

thực hiện chức năng chỉ bằng this.bar, thuộc phạm vi này (foo). Khi bạn sao chép này.bar để barf, và chạy barf. Javascript được hiểu là, chạy hàm được chỉ định bởi barf và vì không có này, nó chỉ chạy trong phạm vi toàn cầu.

Để khắc phục điều này, bạn có thể thay đổi

barf(); 

một cái gì đó như thế này:

barf.apply(this); 

này cho Javascript để ràng buộc phạm vi này để barf trước khi thực hiện nó.

Đối với sự kiện jquery, bạn sẽ cần phải sử dụng chức năng ẩn danh hoặc mở rộng hàm kết buộc trong mẫu thử nghiệm để hỗ trợ phạm vi.

Để biết thêm thông:

+2

Tôi không chắc chắn 100% về thuật ngữ, nhưng tôi nghĩ câu trả lời này (và các tài nguyên được liên kết) gây nhầm lẫn 'phạm vi' với 'ngữ cảnh thực thi'. Đối tượng được trỏ đến bởi 'this' là * context thực thi *, và hoàn toàn độc lập với * scope * (mà các bao đóng phải làm). Phạm vi được xác định tại thời gian tạo của hàm và xác định các biến mà hàm có thể thấy; ngữ cảnh thực thi được xác định bất cứ khi nào hàm được gọi và xác định cái 'này' đề cập đến. Thay thế 'phạm vi' bằng 'ngữ cảnh thực thi' ở khắp mọi nơi ở đây và chỉ sau đó nó sẽ chính xác - tôi nghĩ vậy! –

1

Điều này là do này luôn luôn là trường hợp mà chức năng được gắn vào. Trong trường hợp của EventHandler, đó là lớp đã kích hoạt sự kiện.

Bạn có thể giúp bạn tự với một chức năng vô danh như thế này:

function foo() { 
    var obj = this; 
    $("#thing").after($("<div>click me</div>").click(function(){obj.bar();})); 
} 

foo.prototype.bar = function() { 
    alert(this); 
} 
2

Bạn có thể sử dụng Function.apply vào chức năng để thiết lập những gì this nên tham khảo:

$("#thing").after($("<div>click me</div>").click(function() { 
    barf.apply(document); // now this refers to the document 
}); 
+1

Bên cạnh thực tế là có một khung đóng bị thiếu ở mã của bạn - hàm * áp dụng * ngay lập tức thực hiện chức năng * barf * thay vì trả về một con trỏ hàm. – Martin

+0

Cảm ơn, bây giờ tôi đã sửa bài viết :) – moff

5

Có một lời giải thích tốt về this từ khóa trong JavaScript có sẵn tại QuirksMode.

0
this.bar(); // when called here, "this" is the foo instance 

nhận xét này là sai khi foo được sử dụng như một chức năng bình thường, không phải là một nhà xây dựng. tại đây:

foo();//this stands for window