2009-07-08 30 views
16

Tôi đang cố gắng để có được các nguyên tắc làm chức năng kiểu jQuery chuỗi thẳng trong đầu của tôi. Ý tôi là:Chuỗi đối tượng/hàm cơ bản hoạt động như thế nào trong javascript?

var e = f1('test').f2().f3(); 

Tôi đã có một ví dụ để làm việc, trong khi một ví dụ khác thì không. Tôi sẽ đăng những người dưới đây. Tôi luôn luôn muốn tìm hiểu nguyên tắc cơ bản đầu tiên về cách thức hoạt động của một thứ gì đó để tôi có thể xây dựng trên nó. Cho đến bây giờ, tôi chỉ có một sự hiểu biết ngắn gọn và ngớ ngẩn về cách chuỗi hoạt động và tôi đang chạy vào các lỗi mà tôi không thể khắc phục sự cố một cách thông minh.

Những gì tôi biết:

  1. Chức năng phải trả lại bản thân, hay còn gọi là "trở lại này;"
  2. Chức năng có thể khóa phải nằm trong một hàm cha, hay còn gọi là jQuery, .css() là một phương thức con của jQuery(), do đó jQuery(). Css();
  3. Chức năng gốc phải trả về chính nó hoặc một bản sao mới của chính nó.

Ví dụ này làm việc:

var one = function(num){ 
    this.oldnum = num; 

    this.add = function(){ 
     this.oldnum++; 
     return this; 
    } 

    if(this instanceof one){ 
     return this.one;  
    }else{ 
     return new one(num);  
    } 
} 
var test = one(1).add().add(); 

Nhưng cái này không:

var gmap = function(){ 

    this.add = function(){ 
     alert('add'); 

     return this;  
    } 

    if(this instanceof gmap) { 
     return this.gmap; 
    } else{ 
     return new gmap(); 
    } 

} 
var test = gmap.add(); 
+6

Các chức năng không tự trả lại, chúng trả về đối tượng hỗ trợ các phương thức bạn đang chuỗi. Trong trường hợp jQuery, nó là nút đang được vận hành. – drudru

+1

Yêu cầu mỗi hàm kết thúc bằng 'trả về kết quả này;'. –

+0

@MarcB - Tôi biết, nhưng làm thế nào? –

Trả lời

32

Trong hàm JavaScript là đối tượng hạng nhất. Khi bạn định nghĩa một hàm, nó là hàm tạo cho đối tượng hàm đó. Nói cách khác:

var gmap = function() { 
    this.add = function() { 
     alert('add'); 
    return this; 
    } 

    this.del = function() { 
     alert('delete'); 
     return this; 
    } 

    if (this instanceof gmap) { 
     return this.gmap; 
    } else { 
     return new gmap(); 
    } 
} 
var test = new gmap(); 
test.add().del(); 

Bằng cách chỉ định các

new gmap();
để kiểm tra biến bây giờ bạn đã xây dựng một đối tượng mới "thừa hưởng" tất cả các thuộc tính và phương pháp từ GMap() constructor (class). Nếu bạn chạy đoạn mã ở trên, bạn sẽ thấy cảnh báo cho "thêm" và "xóa".

Trong ví dụ ở trên, "this" đề cập đến đối tượng cửa sổ, trừ khi bạn quấn các hàm trong một hàm hoặc đối tượng khác.

Lúc đầu tôi gặp khó khăn để hiểu, ít nhất nó là dành cho tôi, nhưng một khi tôi hiểu nó, tôi đã nhận ra sức mạnh của một công cụ có thể.

4

Đáng buồn thay, câu trả lời trực tiếp phải là 'không'. Thậm chí nếu bạn có thể ghi đè lên các phương pháp hiện có (mà bạn có lẽ có thể trong nhiều UAS, nhưng tôi nghi ngờ không thể trong IE), bạn sẽ vẫn bị mắc kẹt với lại tên khó chịu:

HTMLElement.prototype.setAttribute = function(attr) { 
    HTMLElement.prototype.setAttribute(attr) //uh-oh; 
} 

Điều tốt nhất bạn có thể có thể nhận được ngay với đang sử dụng một tên khác:

HTMLElement.prototype.setAttr = function(attr) { 
    HTMLElement.prototype.setAttribute(attr); 
    return this; 
} 
+0

Có vẻ như tôi sẽ dính vào jQuery để chuỗi! –

+1

Xin lưu ý câu trả lời này là [câu hỏi khác] (http://stackoverflow.com/questions/10965781) – kojiro

1

Để "viết lại" hàm, nhưng vẫn có thể sử dụng phiên bản gốc, trước tiên bạn phải gán hàm ban đầu cho một biến khác. Giả sử một đối tượng dụ:

function MyObject() { }; 

MyObject.prototype.func1 = function(a, b) { }; 

Để viết lại func1 cho chainability, làm điều này:

MyObject.prototype.std_func1 = MyObject.prototype.func1; 
MyObject.prototype.func1 = function(a, b) { 
    this.std_func1(a, b); 
    return this; 
}; 

Dưới đây là một working example. Bạn chỉ cần sử dụng kỹ thuật này trên tất cả các đối tượng tiêu chuẩn mà bạn cảm thấy cần có khả năng chainability.

Bởi thời gian bạn làm tất cả những công việc này, bạn có thể nhận ra rằng có những cách tốt hơn để thực hiện những gì bạn đang cố gắng để làm, như sử dụng một thư viện mà đã có chainability xây dựng trong. * ho * jQuery * ho *

+0

Đây là giải pháp chung: http://stackoverflow.com/a/15797662/162793 – sheldonh

-3

Chỉ cần gọi phương thức là var test = gmap(). add();

dưới dạng gmap là hàm không phải là biến

+0

Điều này sẽ không hoạt động vì 'add' không được định nghĩa trên' gmap() ', nhưng chỉ trên' gmap mới() '. –

0

Trước tiên, hãy để tôi nói rằng tôi đang giải thích điều này theo cách của riêng tôi.

Phương pháp chuỗi là gọi khá nhiều phương thức của đối tượng được trả về bởi một hàm/phương thức khác. ví dụ: (sử dụng jquery):

$('#demo'); 

Hàm jquery này chọn và trả về đối tượng jquery thành phần DOM với bản demo id. nếu phần tử là một nút văn bản (phần tử), chúng ta có thể chuỗi trên một phương thức của đối tượng đã được trả về. ví dụ:

$('#demo').text('Some Text'); 

Vì vậy, miễn là hàm/phương thức trả về đối tượng, bạn có thể chuỗi phương thức của đối tượng được trả lại cho câu lệnh gốc.

Vì lý do sau này không hoạt động, hãy chú ý đến vị trí và thời điểm từ khóa this được sử dụng. Nó rất có thể là một vấn đề ngữ cảnh. Khi bạn đang gọi this, hãy đảm bảo rằng this đề cập đến chính đối tượng hàm đó, không phải đối tượng cửa sổ/phạm vi toàn cục.

Hy vọng điều đó sẽ hữu ích.

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