2012-02-19 24 views
52

Tôi cần viết một vài phương thức mở rộng trong JS. Tôi biết chỉ làm thế nào để làm điều này trong C#. Ví dụ:Làm cách nào để viết một phương thức mở rộng bằng JavaScript?

public static string SayHi(this Object name) 
{ 
    return "Hi " + name + "!"; 
} 

và sau đó được gọi bởi:

string firstName = "Bob"; 
string hi = firstName.SayHi(); 

Làm thế nào tôi sẽ làm một cái gì đó như thế này trong JavaScript?

Trả lời

94

Trong trường hợp cụ thể, bạn muốn chỉ định phương pháp của bạn để String.prototype, như thế này:

String.prototype.SayHi = function SayHi() { 
    return "Hi " + this + "!"; 
}; 

hoặc tốt hơn là một tài sản không đếm được sử dụng Object.defineProperty (ES5 và cao hơn, vì vậy về cơ bản, tất cả mọi thứ nhưng IE8 và trước đó):

Object.defineProperty(String.prototype, "SayHi", { 
    value: function SayHi() { 
     return "Hi " + this + "!"; 
    } 
}); 

JavaScript là ngôn ngữ nguyên mẫu. Điều đó có nghĩa là mọi đối tượng đều được hỗ trợ bởi đối tượng nguyên mẫu . Trong JavaScript, nguyên mẫu đó được gán bởi hàm hàm dựng cho đối tượng hoặc bằng hàm mới (ish) ECMAScript5 Object.create.

Trong trường hợp cũ (hàm khởi tạo), nguyên mẫu được gán cho một đối tượng được xác định bởi thuộc tính prototype của hàm tạo. Vì vậy, nếu bạn đã một hàm constructor được gọi là Foo:

function Foo() { 
} 

... sau đó báo cáo kết quả

var f = new Foo(); 

... gán Foo.prototype đến dụ f như đối tượng nguyên mẫu của nó. Như vậy:

function Foo(b) { 
    this.baz = b; 
} 
Foo.prototype.bar = function bar() { 
    console.log(this.baz); 
}; 

var f = new Foo("Charlie"); 
f.bar(); // logs "Charlie" 

Vì vậy, trong ví dụ của bạn, vì firstName là một trường hợp String (thực sự là một chuỗi nguyên thủy, nhưng đừng lo lắng, nó được Automagically thăng một trường hợp String bất cứ khi nào cần thiết), nguyên mẫu của nó là String.prototype, vì vậy thêm thuộc tính vào String.prototype tham chiếu hàm SayHi của bạn làm cho hàm đó khả dụng trên tất cả các trường hợp String.

DougR được chỉ ra trong nhận xét, một khác biệt với phương pháp mở rộng C# là phương pháp mở rộng của C# can be called on null references (nếu bạn có phương thức mở rộng string, string s = null; s.YourExtensionMethod(); thực sự hoạt động). Điều này không đúng với JavaScript; null là loại riêng của nó và không có nguyên mẫu để mở rộng cho nó.


Lưu ý nhanh về tên hàm trong ví dụ đó, ví dụ:

Object.defineProperty(String.prototype, "SayHi", { 
    value: function SayHi() { 
// HERE ------------^ 
     return "Hi " + this + "!"; 
    } 
}); 

Foo.prototype.bar = function bar() { 
// AND HERE -----------------^ 
    console.log(this.baz); 
}; 

Đó hình thức, nơi mà chúng tôi đang sử dụng một biểu thức chức năng với một tên trong đó (gọi là "tên biểu hiện chức năng," aka NFE) từng là nổi tiếng vì có vấn đề (trên IE8 và trước đó; và trên các phiên bản thực sự, thực sự cũ của một vài trình duyệt khác). Với mọi thứ khác bị chết và IE8 là gần như đã chết, không cần phải lo lắng về NFE nữa.(Và ở trên sẽ không sao ngay cả trong IE8.)

+0

@DougR: Xin lỗi, dọn dẹp bình luận tiêu chuẩn. Khi một bình luận trở nên lỗi thời, mod hoặc người dùng có quyền lực có thể loại bỏ nó (mods có thể làm điều đó trực tiếp, người dùng quyền lực phải nhóm lên trong hàng đợi đánh giá). Tôi đã cập nhật câu trả lời để gọi ra rằng bạn đã gắn cờ điều này. :-) –

+1

@Grundy: Cảm ơn, vâng, toàn bộ điểm của phần 'String s = null; 'là sử dụng' s.YourExtensionMethod() '! Đánh giá cao sản lượng khai thác. :-) –

+0

Cảm ơn bạn đã đánh dấu phương thức mở rộng đó hoạt động cho các thực thể null. – Rama

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