2011-11-22 20 views
7

Tôi rất quen thuộc với các chức năng tự thực thi khi làm việc với jQuery.Chức năng tự thực thi JavaScript - Sự khác biệt là gì?

(function($) { /* do stuff */ })(jQuery); 

Hôm nay tôi đã đọc nguồn backbone.js và nhận thấy rằng họ làm điều này:

(function() { /* do stuff */ }).call(this); 

Đây có phải là đạt được điều tương tự? Liệu 2 dòng mã sau đây có làm điều tương tự không?

(function($) { /* do stuff */ })(jQuery); 
(function($) { /* do stuff */ }).call(jQuery); 

Trả lời

12

Biểu mẫu đầu tiên được chuyển trong tham số, trong khi biểu mẫu thứ hai đang đặt nội dung 'này' đề cập đến bên trong hàm thi hành. Họ khác nhau.

(function(x){ console.log(this,x); })(jQuery); 
//--> [window object] 
//--> [jQuery object] 

(function(x){ console.log(this,x); }).call(jQuery); 
//--> [jQuery object] 
//--> undefined 

(function(x){ console.log(this,x); }).call(jQuery, jQuery); 
//--> [jQuery object] 
//--> [jQuery object] 

Để biết thêm thông tin, xem Function.prototype.callFunction.prototype.apply.

Dưới đây là một trường hợp mà bạn có thể muốn sử dụng call kỹ thuật:

v = 'oh noes!' 
var o = { 
    v : 42, 
    f : function(){ 
    console.log(this.v); 
    (function(){ console.log(this.v) })(); 
    } 
}; 
o.f(); 
// --> 42 
// --> 'oh noes!' 

Nếu không thiết lập các giá trị của this qua call(), chức năng tự gọi được gọi trong phạm vi toàn cầu (cửa sổ) , không phải đối tượng hiện tại.

+1

mặc dù nếu đó là 'cuộc gọi (jQuery, jQuery)' thì nó sẽ đặt cả hai. – zzzzBov

+0

@Phrogz Cảm ơn. Tôi hiểu rồi. – modernzombie

+0

@zzzzBov cả hai sẽ là [đối tượng jQuery], đúng không? – modernzombie

3

Trong trường hợp của chúng:

(function() { /* do stuff */ }).call(this); 

... họ đang đảm bảo rằng các chức năng được gọi với một giá trị cụ thể cho this (ví dụ: this bên trong hàm sẽ được giống như this ngoài chức năng).

Trong trường hợp của bạn:

(function($) { /* do stuff */ })(jQuery); 

... this trong chức năng của bạn sẽ là đối tượng toàn cầu, bởi vì bạn đã gọi nó mà không làm bất cứ điều gì mà bộ this, vv this giá trị mặc định cho các đối tượng toàn cầu (window, trên browers).

Trong JavaScript, this được đặt hoàn toàn bằng cách gọi hàm. Có hai cách chính:

  1. Bằng cách gọi hàm như một phần của biểu thức truy xuất nó từ thuộc tính đối tượng, ví dụ:

    obj.foo(); // Or `obj["foo"](); 
    

    Trong trường hợp đó, trong cuộc gọi đến foo, this sẽ đề cập đến obj.

  2. Bằng cách gọi hàm qua nó được xây dựng trong call hoặc apply phương pháp:

    var obj = {name: "Fred"}; 
    function foo(salutation, punctuation) { 
        alert(salutation + " " + this.name + punctuation); 
    } 
    foo.call(obj, "Hi", "!"); // alerts "Hi Fred!" 
    foo.apply(obj, ["Hi", "!"]); // Also alerts "Hi Fred!" 
    

    Sự khác biệt duy nhất giữa callapply là như thế nào bạn chỉ định đối số để truyền vào các chức năng bạn đang gọi điện thoại: Với call , bạn chỉ cần liệt kê chúng dưới dạng đối số rời rạc sau giá trị this bạn muốn; với apply, bạn cung cấp chúng dưới dạng mảng.

+2

Tôi ước tôi có thể +2 hoặc +3 bạn để có thông tin tuyệt vời. – Phrogz

-2

.call đặt chức năng vào phạm vi đóng.

Vì vậy, nếu bạn đã làm điều này:

(function($) { /* do stuff */ }).call(jQuery); 

$ sẽ undefined

+1

-1 cho thuật ngữ khó hiểu/không chính xác; 'call' không liên quan gì đến việc đóng cửa. – Phrogz

1

Đầu tiên đi jQuery như tham số $. Thứ hai làm cho jQuery biến 'this' bên trong hàm.

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