2009-12-29 29 views

Trả lời

24

Việc sử dụng apply có liên quan đến ngữ cảnh chức năng (từ khóa this) và đối số chuyển.

Trước tiên, tôi nghĩ rằng bạn nên biết trong đó trường hợp các từ khóa thisngầm thiết lập:

1- Khi một hàm được gọi là một phương pháp (hàm được gọi là thành viên của một đối tượng):

obj.method(); // 'this' inside method will refer to obj 

2- Một chức năng cuộc gọi bình thường:

myFunction(); // 'this' inside the function will refer to the Global object 
// or 
(function() {})(); 

3- Khi new nhà điều hành được sử dụng:

var obj = new MyObj(); // this will refer to a newly created object. 

Dưới đây là khi applycall đến, các phương pháp đó cho phép bạn đặt rõ ràng bối cảnh khi bạn gọi một chức năng, Eg .:

function test(a) { 
    alert(this + a); 
} 

test.call('Hello', ' world!'); 

Trong đoạn mã trên , khi hàm test được gọi là đặt từ khóa this thành Chuỗi ('Hello') và chuyển đối số a (' world.').

Cả, callapply thay đổi bối cảnh của hàm thực hiện (từ khóa this) bên trong hàm gọi, nhưng chênh lệch giữa chúng là với apply, bạn có thể gửi một mảng hoặc một mảng giống như đối tượng như các đối số của hàm được thực thi, mà là cực kỳ hữu ích, ví dụ:

function sum() { 
    var result = 0; 
    for (var i = 0; i < arguments.length; i++) { 
    result += arguments[i]; 
    } 
    return result; 
} 

var args = [1,2,3]; 
sum.apply(null, args); // will return 6 

Điều đó có thể tránh được một số rất hacky, xấu (và thường) eval cuộc gọi như:

eval('sum(' + args.join() +')'); 

Một ví dụ khác, các Math.maxMath.min phương pháp, các phương pháp đó có thể nhận được một số tùy ý của lập luận như:

var max = Math.max(2,4,6,8); // 8 

Nhưng nếu bạn có một mảng các số?

var numbers = [2,4,6,8]; 
numbers.push(10); 
var max = Math.max.apply(null, numbers); // 10 

Cũng lưu ý rằng khi null hoặc undefined được sử dụng như là đối số this với call hoặc apply, đối tượng this sẽ đề cập đến đối tượng toàn cầu (tương tự như trường hợp # 2, chức năng bình thường gọi).

Đối với ví dụ Math.max, bối cảnh là không thực sự có liên quan, vì chúng là giống như "tĩnh" phương pháp, các từ khóa this không được sử dụng trong nội bộ ...

+3

+1 Rất đẹp! ---- –

+0

Ah Tôi nghĩ mình đã hiểu rồi. Toàn bộ điểm mà tôi đã bỏ lỡ là "giá trị của điều này được cung cấp như các tham số đầu tiên". Bây giờ nó có ý nghĩa lý do tại sao chúng tôi muốn phân biệt phương pháp áp dụng như là một loại riêng biệt của invocation. Vậy khác biệt là gì. giữa cuộc gọi và áp dụng các từ khóa sau đó? – Priyank

+0

@cms +1 hoàn hảo để in! –

0

Tôi không biết về bất kỳ thiết kế các mẫu có tên Mẫu áp dụng nên tôi không thực sự nghĩ rằng điều này có liên quan đến các mẫu thiết kế. Tuy nhiên, có một phương pháp áp dụng các đối tượng hàm trong javascript (cùng với phương thức gọi tương ứng) vì vậy tôi sẽ giải thích chúng.

Phương pháp áp dụng và gọi cơ bản cho phép đối tượng "lấy cắp" một phương thức từ đối tượng khác. Bạn thấy đấy, trong javascript, các phương thức bị ràng buộc rất muộn: tại thời điểm yêu cầu. Chỉ khi phương thức được gọi là giá trị của 'this' được giải quyết. Trong cuộc gọi phương thức thông thường:

some_object.do_something(); 

'this' từ khóa trong do_something đề cập đến some_object. Áp dụng và gọi cho phép bạn chỉ định lại 'this'. Ví dụ:

some_object.do_something.apply(another_object); 

'this' từ khóa trong do_something bây giờ đề cập đến another_object. Vì vậy, bạn đang gọi phương thức do_something thuộc some_object trên another_object.

Bây giờ, điều này thật thú vị và tất cả nhưng tại sao mọi người lại muốn làm điều này? Dưới đây là ví dụ cụ thể về lý do tại sao điều này hữu ích:

// say you want to get some DIVs in the document, you can get all of them with: 
var some_divs = document.getElementsByTagName('DIV'); 

// say you want the third to fifth DIV in the document, some_divs looks like an 
// array so you might think you can slice it, but it's not. It's a collection 
// of elements that fakes being an array and doesn't implement the slice method. 

// No worries, we can steal the slice method from an array 
// and apply it to some_divs: 
var wanted_divs = [].slice.apply(some_divs,[2,5]); 

// Alternatively: 
var wanted_divs = [].slice.call(some_divs,2,5); 

Có một trường hợp sử dụng khác là kết quả của sự khác biệt giữa cách áp dụng và cuộc gọi. Nếu bạn có tất cả các đối của bạn trong một mảng và chức năng hy vọng đối số cá nhân mà bạn có thể sử dụng áp dụng để vượt qua mảng và có chức năng xem nội dung của mảng như các đối số cá nhân:

function some_function (first,second) { 
    alert(first+second); 
} 
var argument_array = ['hello','world']; 
some_function.apply(null, argument_array); 
1

Bạn cũng có thể sử dụng cuộc gọi/áp dụng cho thừa kế.

function Client (id) { 
    this.id = id; 
    this.name = "Client" + id; 
} 

Client.prototype = { 
    constructor: Client 

    , toString: function() { 
     return this.name; 
    } 
}; 

function WebClient (id) { 
    Client.call (this, id); 
} 

WebClient.prototype = new Client(); 

WebClient.prototype.constructor = WebClient; 

WebClient.prototype.ping = function() { 
    // do stuff 
}; 

Thông báo Client.call (this, id); này thực hiện bằng cách sử dụng Clientthis dụ rằng một new WebClient sẽ tạo ra. Vì vậy khi

this.id = id; 
    this.name = "Client" + id; 

được thực hiện bên trong Client sơ thẩm WebClient là nhận được giao những tài sản.

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