2012-04-12 17 views
7

Chúng được lấy từ hướng dẫn Jquery vid tuts-premium.
http://tutsplus.com/lesson/the-this-keyword/ Jeff giải thích điều này 'đang đề cập đến mỗi lần nhưng tôi không chắc mình đã nắm được lý do đằng sau tất cả.4 kịch bản khác nhau của 'điều này'. Giải thích đúng là gì?

Ví dụ: 1

function doSomething(e) { 
e.preventDefault(); 
console.log(this); 
} 

$('a').on('click', doSomething); 

Trong trường hợp này "này đề cập đến 'a' yếu tố" (là trong trường hợp này đối tượng phụ huynh)

Tôi đoán đó là bởi vì đây báo cáo kết quả tương đương với:

$('a').on('click', function (e) { 
    e.preventDefault(); 
    console.log(this); 
    } 

Vì vậy 'a' là đối tượng gốc

Ví dụ: 2

var obj = { 
    doIt: function(e){ 
    e.preventDefault(); 
    console.log(this); 
    } 
} 

$('a').on('click', obj.doIt); 

Trong trường hợp này "này vẫn đề cập đến 'a' yếu tố" (* nhưng dường như nó không phải là đối tượng cha?)

Có vẻ như lần này chúng tôi đang gọi điện thoại một phương pháp nhưng tuyên bố vẫn tương đương với điều tương tự như ví dụ 1

* Một điều trong hướng dẫn có một chút nhầm lẫn. Tôi nghĩ rằng 'điều này' luôn luôn đề cập đến đối tượng cha mẹ vì vậy trong trường hợp này 'a' vẫn là đối tượng cha mẹ. Nhưng (tại 05.23 trong hướng dẫn), anh ta không phải là trường hợp, nói rằng "có thể có những lúc bạn muốn 'cái này" ám chỉ đối tượng cha của nó, đó là' obj '"trong sự kiện mà anh tạo ra, ví dụ.

Ví dụ: 3

var obj = { 
    doIt: function(){ 
    console.log(this); 
    } 
} 

$('a').on('click', function(e){  
obj.doIt(); 
     }; 
e.preventDefault(); 

Trong trường hợp này "này đề cập đến đối tượng obj"

Tôi đoán này đến với thực tế là 'này' được trong một hàm lồng nhau như tuyên bố này tương đương với:

$('a').on('click', function(){  
function(){ console.log(this);} 
}; 
e.preventDefault(); 

Tôi thực sự không hiểu lý do tại sao, đặc biệt là khi tôi đọc trong một bài báo trong các hàm lồng nhau 'this' "bị mất và tham chiếu đến đối tượng đầu (đối tượng cửa sổ)".

Eg4

var obj = { 
    doIt: function(){ 
    console.log(this);  
    } 
} 

$('a').on('click', function(e){  
     obj.doIt.call(this);    
     e.preventDefault(); 
}); 

Trong trường hợp này "này đề cập đến 'a'"

Theo Javascript Definitive Guide "Đối số đầu tiên cho cả cuộc gọi() là đối tượng mà chức năng này được gọi là " Ở đây" này "được sử dụng làm đối số đầu tiên. Nhưng "điều này" không phải là đối tượng mà trên đó hàm được gọi?
Tôi nghĩ rằng tôi nhận được hàm gọi ở đó để gọi hàm và sử dụng tham số đầu tiên của nó làm con trỏ đến một đối tượng khác nhưng tôi không hiểu tại sao sử dụng 'this' có nghĩa là hàm được gọi bởi 'a'. Nó không phải là một cái gì đó tôi đã nhìn thấy trong cuộc gọi khác() ví dụ hoặc.

Xin lỗi vì bài đăng khổng lồ này.Hy vọng rằng ai đó vẫn đang đọc theo giai đoạn này…

+0

+1 vì đã quá muộn để tôi bắt đầu trả lời vào câu hỏi tuyệt vời này. Không có nghi ngờ một người khác sẽ sớm - đó là một điểm quan trọng và một trong đó thường được bảo hiểm kém trong JS hướng dẫn. – jimw

+3

* "Tôi nghĩ 'điều này' luôn đề cập đến đối tượng cha mẹ ..." * Không, đừng nghĩ 'điều này' làm đối tượng cha mẹ. Hãy nghĩ về nó như là một ngữ cảnh * gọi * có giá trị có thể được thiết lập theo nhiều cách khác nhau, một trong số đó xảy ra khi gọi một phương thức từ một đối tượng. –

Trả lời

4

Tôi hy vọng điều này sẽ giúp làm sáng tỏ vấn đề, thực sự có thể khó hiểu.

  • Khi this là lỏng lẻo trên mã của bạn, nó sẽ giới thiệu cho các đối tượng toàn cầu (trong các trình duyệt web, có nghĩa là window).

    console.log(this); // window 
    
  • Khi this là bên trong một phương pháp đối tượng (như trên của bạn ví dụ: 3), nó sẽ giới thiệu cho các đối tượng. Điều này aplies cho các đối tượng instanced với new, hoặc như là đối tượng literals (như trên ví dụ của bạn).

    var obj = { 
        doIt: function(e){ 
         console.log(this); 
        } 
    } 
    obj.doIt(); // obj 
    
  • Bên trong phương thức thụ lý sự kiện, this sẽ tham khảo các đối tượng sự kiện là ràng buộc để.

    // This is the plain js equivalent of your jQuery example 
    document.getElementsByTagName['a'][0].addEventListener('click', function(e){ 
        console.log(this); // the first anchor on the document 
    }); 
    
    // This is exactly the same: 
    var clickHandler = function(e){ 
        console.log(this); // the first anchor on the document 
    }; 
    document.getElementsByTagName['a'][0].addEventListener('click', clickHandler); 
    
    // Even if the handler is defined inside of another object, this will be 
    // the obj the event is bound to. It's the case of your E.g. 2 
    var obj = { 
        doIt: function(e){ 
         console.log(this); // the first anchor on the document 
        } 
    } 
    document.getElementsByTagName['a'][0].addEventListener('click', obj.doIt); 
    // When you pass obj.doIt to addEventListener above, you are passing a reference 
    // to that function. It's like "stealing" the function from the object 
    
  • Khi một đối tượng được thông qua như là tham số đầu tiên Function.call hoặc Function.apply, nếu this xuất hiện bên trong của hàm nó sẽ đề cập đến đối tượng bạn trôi qua. Đó là một cách để buộc những gì this sẽ trỏ đến.

    var obj = { 
        doIt: function(){ 
         console.log(this); // window 
        } 
    } 
    obj.doIt.call(window); 
    
+0

Tuy nhiên, với 'obj' với hàm' doIt', nếu chúng ta làm 'var fn = obj.doIt; fn() ',' this' sẽ tham chiếu đến 'window' bên trong' fn'. –

+0

Vâng, giống như trong ví dụ của tôi với 'addEventListener' (ngoại trừ trong trường hợp đó nó sẽ trỏ đến một nút DOM, không phải là' cửa sổ'). Nhưng logic là như nhau. – bfavaretto

0

Cách this hoạt động trong JavaScript lúc đầu hơi khó hiểu. Về cơ bản, không giống như các biến (có phạm vi tĩnh), thisđộng phạm vi. Tức là, giá trị của this được xác định bởi nơi bạn gọi hàm thay vì vị trí bạn đã viết.

Khi bạn chuyển hàm của mình tới on, sau đó nó được gọi từ ngữ cảnh trong đó this là phần tử được đề cập. Điều này xảy ra bất kể về cách bạn có chức năng đó. Đó là để nói, một chức năng không quan tâm cho dù bạn truy cập nó bằng cách sử dụng cú pháp như obj.fn hoặc chỉ tên của nó fn - giá trị của biểu thức là như nhau trong cả hai trường hợp.

Với những thứ khác ngoài chức năng, điều này có ý nghĩa. Given:

var a = 10, 
    obj = { a : 10 }; 

bạn sẽ đồng ý rằng biểu thức aobj.a có cùng giá trị. Điều này cũng đúng với các chức năng.

Tóm lại: giá trị this tùy thuộc vào vị trí và cách bạn gọi hàm thay vì cách bạn đã khai báo hoặc cách bạn đã gọi nó trước khi gọi.

+3

Chúng ta không nên nhầm lẫn 'this' với' scope '. Chúng hoàn toàn tách biệt. Và 'this' không được xác định bởi * trong đó *, mà là bởi * cách * hàm được gọi. –

+0

Xem xét kỹ hơn, có một vài điều sai. Giống như ... * "... nó sau đó được gọi từ một bối cảnh mà đây là phần tử được đề cập" *. Điều này làm cho không có sự khác biệt. Không có sự chuyển giao của bối cảnh kèm theo vào một ngữ cảnh được gọi trừ khi bạn chuyển nó bằng cách sử dụng '.call()' hoặc '.apply()'. Và điều này ... * "... một chức năng không quan tâm cho dù bạn truy cập nó bằng cách sử dụng cú pháp như' obj.fn' hay chỉ tên của nó 'fn'" * ... cũng không đúng. Nó rất nhiều tạo nên sự khác biệt. –

+0

Điểm của tôi là biểu thức 'f' và' obj.f' có cùng giá trị (miễn là 'f' và' obj.f' trỏ đến cùng một hàm). Có lẽ tôi không đủ rõ ràng về điều đó. Đối với các điểm khác, bạn có thể thay đổi giá trị của 'this' mà không có' call' hoặc 'apply' bằng cách đặt hàm trong đối tượng. Vì vậy, cho dù bạn * gọi * nó từ một đối tượng hoặc bởi chính nó vấn đề, nhưng chỉ cần truy cập nó (nhận được chức năng như một giá trị) nó không quan trọng. –

0

Thật đánh giá cao những phản ứng guys. Tôi đã đăng trong những giờ đầu và đã cố gắng (& cần thiết) để dành một chút thời gian để tiêu hóa phản hồi của bạn.

https://developer.mozilla.org/en/JavaScript/Reference/Operators/this là một tiếng hét lớn. Tôi đã đọc khá ít bài báo/tuts và điều này dường như là một trong những bài viết hay hơn.

Tôi nghĩ rằng giác ngộ chính là đối tượng liên kết với 'điều này' được xác định bằng cách/nơi hàm được gọi (ngữ cảnh gọi) thay vì cách thức hoặc vị trí hàm được xác định.

Vì vậy, chỉ để trở lại điều cần Q & Một phạm vi và cố gắng trả lời Q của riêng tôi trong ánh sáng của những gì các bạn đã trả lời ...

Ví dụ: 1 Ở đây: chức năng 'doSomething' được gọi trong ngữ cảnh của trình xử lý nhấp chuột để đối tượng được liên kết với 'this' là "a"

Ví dụ: 2 Một lần nữa, trình xử lý nhấp chuột vẫn kích hoạt chức năng để đối tượng được liên kết với 'this' là "a"

Ví dụ: 3 Trong hàm lồng nhau, ngữ cảnh gọi là obj.doIt(). Vì vậy, như ông nói trong hướng dẫn, đối tượng ràng buộc với 'điều này' là "obj".

Mặc dù, dựa trên logic tương tự từ developer.mozilla.org ví dụ dưới đây, không phải là đối tượng thực sự ràng buộc để "obj.doIt":

o.b = {g: independent, prop: 42};   
console.log(o.b.g()); // logs 42   

"sự ràng buộc này chỉ bị ảnh hưởng bởi nhiều nhất tham chiếu thành viên ngay lập tức… điều này bên trong hàm sẽ ám chỉ đến ob Thực tế là đối tượng chính nó là một thành viên của o không có hậu quả; tham chiếu ngay lập tức nhất là tất cả những vấn đề quan trọng. "

Ví dụ: 4

Ở đây - 'công việc của người gọi là gián tiếp gọi hàm như thể đó là phương pháp của đối tượng mới - trong trường hợp này chúng tôi đã định nghĩa là' this '. Đây 'này' đề cập đến "a" vì nó là một phần của hàm được kích hoạt bởi trình xử lý nhấp chuột

Tôi hy vọng điều này gần hơn một chút. nhưng tôi vẫn không hoàn toàn tự tin rằng tôi đang đóng đinh khái niệm này

Nếu tôi phải thu thập dữ liệu về lỗ của mình trong một thời gian để tiêu hóa tôi xin lỗi tình trạng mới, sự cố dừng lại Javascript & JQuery chỉ là một vài tuần ngay bây giờ

Xin cảm ơn một lần nữa vì ý kiến ​​phản hồi của mọi người

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