2009-12-26 2 views
35

Câu hỏi của tôi là:chức năng bên này

function Foo() 
{ 
    this.foo = "bar"; // <- What is "this" here? 
} 

Từ những gì tôi có thể nói nó phụ thuộc vào cách Foo được sử dụng, ví dụ như một constructor hoặc như một hàm. Điều gì có thể this trong các trường hợp khác nhau?

Trả lời

46

Từ khóa this đề cập đến đối tượng mà hàm thuộc về hoặc đối tượng window nếu hàm không thuộc đối tượng.

Nó được sử dụng trong mã OOP, để tham khảo các lớp/đối tượng chức năng thuộc về Ví dụ:

function foo() { 
    this.value = 'Hello, world'; 

    this.bar = function() { 
     alert(this.value); 
    } 
} 

var inst = new foo(); 
inst.bar(); 

này cảnh báo: Hello, world

Bạn có thể thao tác mà đối tượng this đề cập đến bằng cách sử dụng các hàm apply() hoặc call(). (Một tính năng rất rất tiện dụng vào những thời điểm)

var bar1 = new function() { 
    this.value = '#1'; 
} 
var bar2 = new function() { 
    this.value = '#2'; 
} 

function foo() { 
    alert(this.value); 
} 

foo.call(bar1); // Output: #1 
foo.apply(bar2, []); // Output: #2 
+3

Tại sao các phiếu bầu xuống? .. Chỉ cần tò mò. – Atli

+0

Tôi cũng tò mò. có điều gì sai với lời giải thích của anh ta không? – goh

+1

Câu trả lời của @Danben đặt trọng tâm vào việc sử dụng từ khóa mới, tạo ra một đối tượng mới (cách nguyên mẫu javascript). Nếu không có nó, không có đối tượng mới được tạo ra và chức năng là "interned" (nếu tôi có thể nói như vậy) với đối tượng nó thuộc về, hoặc đối tượng cửa sổ toàn cục nếu trong trình duyệt. –

-1

Trong JavaScript mọi thứ đều phản đối thậm chí chức năng. Khi bạn nói this.foo trong đoạn mã sau

function Foo() 
{ 
    this.foo = "bar"; // <- What is "this" here? 
} 

foo trở thành thành viên biến Foo đối tượng

+0

Tôi có thể có chức năng MyClass() {function MyMethod() {console.log (this); }} và cuộc gọi nhật ký đó sẽ ghi MyClass, không phải MyMethod. Lưu ý rằng cả MyClass lẫn MyMethod đều là các hàm, nhưng sẽ không có ai gọi hàm MyClass.MyMethod mới() nếu thiết kế không có ý định như vậy. –

+1

Để mở rộng ví dụ của Luka: nếu Foo() không phải là hàm thành viên của một số đối tượng tùy chỉnh, nó sẽ trở thành một hàm thành viên của đối tượng chung ('window' nếu được thực hiện trong trình duyệt web) trong trường hợp này' this' sẽ vẫn trỏ đến 'window' và' foo' sẽ trở thành biến thành viên của 'window'. – JustAMartin

20

đọc những gì Douglas Crockford có nói về vấn đề này, để trích dẫn ông từ A Survey of the JavaScript Programming Language:

Một chức năng là một đối tượng. Nó có thể chứa các thành viên giống như các đối tượng khác. Điều này cho phép một hàm chứa các bảng dữ liệu riêng của nó. Nó cũng cho phép một đối tượng hoạt động như một lớp, chứa một hàm tạo và một tập các phương thức liên quan.

Một hàm có thể là thành viên của một đối tượng. Khi một hàm là một thành viên của một đối tượng, nó được gọi là một phương thức. Có một biến đặc biệt, được gọi là này được thiết lập cho đối tượng khi một phương thức của đối tượng được gọi.

Ví dụ, trong biểu thức foo.bar(), biến này được đặt thành đối tượng foo như một loại đối số thừa cho thanh chức năng. Thanh chức năng sau đó có thể tham khảo điều này để truy cập đối tượng quan tâm.

Trong biểu thức sâu hơn như do.re.mi.fa(), biến này được đặt thành đối tượng do.re.mi, không phải đối tượng làm. Trong một cuộc gọi chức năng đơn giản, điều này được thiết lập để các đối tượng toàn cầu (aka cửa sổ), mà không phải là rất hữu ích. Hành vi chính xác nên có để bảo toàn giá trị hiện tại của điều này, đặc biệt khi gọi các hàm bên trong.

Ngoài ra 'this' có thể thay đổi tùy thuộc vào cách chức năng của bạn được gọi, đọc trên apply functioncall function.

Tôi khuyên bạn nên dành thời gian học tập một trong những tâm trí vĩ đại nhất của JavaScript trong bài thuyết trình (miễn phí) của mình, được liên kết từ here.

+0

+1 cho liên kết bản trình bày – Xinus

6

Trong JavaScript, quy ước (và đây chỉ là một quy ước) là bất kỳ chức năng nào bắt đầu bằng chữ hoa đều được sử dụng làm hàm tạo.Sau đó, người ta sẽ gọi

var foo = new Foo()this sẽ đề cập đến đối tượng mới được tạo sắp được tham chiếu bởi foo.

Tất nhiên, không có gì ngăn bạn tự mình gọi Foo(), trong trường hợp này this sau đó sẽ tham chiếu đến đối tượng mà từ đó hàm được gọi. Để tránh nhầm lẫn, điều đó không được khuyến nghị.

+1

Thật tuyệt khi bạn làm rõ việc sử dụng từ khóa mới, vì hầu như không có người dùng bình thường nào quen thuộc với cách các đối tượng dựa trên nguyên mẫu javascript hoạt động và gây nhầm lẫn quá nhiều. –