2011-10-11 20 views
15

Hãy tưởng tượng chức năng như thế này:Làm cách nào để tạo chức năng có thể khóa trong JavaScript?

function foo(x) { 
    x += '+'; 
    return x; 
} 

Cách sử dụng của nó sẽ như thế nào:

var x, y; 
x = 'Notepad'; 
y = foo(x); 
console.log(y); // Prints 'Notepad+'. 

Tôi đang tìm kiếm một cách để tạo ra chức năng đó là thể kết nối với các chức năng khác.

Hãy tưởng tượng sử dụng:

var x, y; 
x = 'Notepad'; 
y = x.foo().foo().toUpperCase(); // Prints 'NOTEPAD++'. 
console.log(y); 

Làm thế nào tôi sẽ làm điều này?

Trả lời

14

Chắc chắn, các trick là để trả lại đối tượng khi bạn đang thực hiện sửa đổi nó:

String.prototype.foo = function() { 
    return this + "+"; 
} 

var str = "Notepad"; 
console.log(str.foo().foo().toUpperCase()); 

http://jsfiddle.net/Xeon06/vyFek/

Để thực hiện phương pháp này có sẵn trên String, tôi thay đổi đó là nguyên mẫu. Hãy cẩn thận không làm điều này trên Object mặc dù, vì nó có thể gây ra vấn đề khi liệt kê trên tài sản của họ.

+3

bạn nên kiểm tra một thuộc tính trên các kiểu gốc trước khi thêm nó, ví dụ 'if (! ('Foo' trong String.prototype)) {String.prototype.foo = function() {.. .}} ' – keeganwatkins

+0

Nếu bạn muốn mở rộng một đối tượng mà không vi phạm kiểu liệt kê, hãy sử dụng (semi-modern) [' Object.defineProperty'] (https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/ Object/defineProperty): 'Object.defineProperty (String.prototype, {value: function() {return this +" + ";}})'. Theo mặc định, cờ 'enumerable' được đặt thành' false'. – Phrogz

+0

@keeganwatkins có nó là :). Tôi cho rằng OP chỉ hỏi về chuỗi như là một ví dụ, vì vậy tôi giữ cảnh báo ở mức tối thiểu, nhưng đó là một điểm tốt. –

6

Nếu tôi nhớ chính xác, bạn có thể sử dụng "này" làm ngữ cảnh của hàm (đối tượng thuộc về) và trả về để làm cho hàm có thể được chuỗi. Nói cách khác:

var obj = 
{ 
    f1: function() { ...do something...; return this;}, 
    f2: function() { ...do something...; return this;} 
} 

sau đó bạn có thể chuỗi các cuộc gọi như obj.f1().f2()

Hãy nhớ, bạn sẽ không thể đạt được những gì bạn đang mong đợi bằng cách gọi obj.f1() toUpperCase(). - nó sẽ thực hiện f1(), trả về "this" và sẽ cố gắng gọi obj.toUpperCase().