2012-05-10 48 views
5

Tôi đang tìm cách có thể mở rộng nguyên mẫu hàm trong javascript (có nghĩa là, thêm một hàm vào tất cả các hàm). Mục đích là chuyển đổi nó thành một định dạng để trao đổi giữa một ngôn ngữ khác (cụ thể là ruby, chỉ có thể giao tiếp thông qua các chuỗi [trong cài đặt cụ thể này]). Tôi đã có một hệ thống để tôi có thể vượt qua xung quanh loại khác bằng cách định nghĩa một phương pháp to_js trên các đối tượng ruby ​​và một phương pháp to_ruby trên các đối tượng javascript, như vậyMở rộng mẫu thử nghiệm

Number.prototype.to_ruby = function() { return this.toString(); } 

này đang làm việc cho tất cả mọi thứ khác tôi muốn nó, nhưng không phải cho các chức năng. Tôi thể cho nó hoạt động trong chrome bằng cách làm như sau:

_empty = function() {}; 
_empty.__proto__.to_ruby = function() { 
    return 'JSFunction.new(' + this.toString().to_ruby() + ')'; 
}; 

Nhưng điều này không làm việc trong IE (đó là một yêu cầu của hệ thống).

Tôi biết tôi có một đối tượng ở đâu đó để theo dõi các chức năng bằng ID hoặc tương tự, nhưng tôi không thể đảm bảo rằng chúng sẽ được sử dụng với cùng một cá thể tạo ra chúng.

Tất cả các khác thất bại tôi chỉ có thể viết một hàm để đặc biệt thỏa thuận hợp với nó (ví dụ, isFunction(instance) ? fn_to_ruby(instance) : instance.to_ruby(), nhưng tôi thà giữ mô hình này nếu có thể.

+0

Hah! Tôi chỉ tình cờ nhìn vào cùng một thứ. SketchUp Ruby <-> Cầu JavaScript. : D – thomthom

Trả lời

2

__proto__ không phải là thuộc tính chuẩn. Hãy thử phương pháp này:

(function(){}).constructor.prototype.to_ruby = function(){ 
    return 'JSFunction.new(' + this.toString().to_ruby() + ')'; 
}; 
+0

Ah! Việc thêm '.constructor' cho tôi chức năng mà tôi đang tìm kiếm - cảm ơn! – DanielB

+2

Bạn phải được nhân vật trả tiền. '(function() {}). constructor.prototype' chỉ là' Function.prototype'. Và gọi 'someObj.to_ruby()' sẽ giống hệt với '" "+ someObj' – RobG

+0

@RobG, bạn đúng - và tất nhiên bây giờ tôi đã thấy nó, nó có ý nghĩa hoàn hảo. cảm ơn :) – DanielB

-1

Các __proto__ không phải là một phần của bất kỳ tiêu chuẩn JavaScript nó chỉ một pesudo-tiêu chuẩn mà một số các nhà sản xuất trình duyệt đã quyết định để thực hiện. IE là một trong đó chưa thực hiện nó.

Nếu bạn muốn thay đổi bất kỳ loại trong hệ thống kiểu JavaScript sau đó bạn sẽ phải để sửa đổi nguyên mẫu Object:

Object.prototype.foo = function() { console.log('foo'); }; 
(1).foo(); 
'asd'.foo(); 
(true).foo(); 
({ bar: 'baz' }).foo(); 
3

Như Slace nói, bạn có thể thêm phương pháp này cho tất cả các đối tượng bằng cách thêm vào Object.prototype, nhưng đó không phải là thực sự kosher vì nó có thể ảnh hưởng nặng bằng văn bản for..in vòng.

Bạn có thể thêm nó chỉ đến chức năng thông qua Function.prototype:

Function.prototype.to_ruby = function() { 
    return this.toString(); 
} 

Tuy nhiên có một nguyên tắc chung là bạn không nên sửa đổi được xây dựng trong các đối tượng, chủ yếu là bởi vì bạn không bao giờ biết khi nào nó sẽ quay trở lại ám ảnh bạn (ví dụ: phiên bản ECMAScript mới triển khai thuộc tính có cùng tên). Có lẽ bạn đang tốt hơn để viết một đơn toRuby chức năng:

function toRuby(obj) { 
    return obj.toString(); 
} 

nhưng bạn cũng có thể cũng sử dụng toán tử + để nối với một chuỗi để gọi toString phương pháp ngầm:

'' + obj; // returns obj.toString() 

đó sẽ trở lại chính xác kết quả tương tự như cả hai bên trên. Lựa chọn của bạn.

+0

Tôi hiểu đối số của bạn, nhưng tôi có một số loại đối tượng khác nhau mà tất cả cần phải trả về một cách hơi khác nhau. Vì vậy, điều này sẽ làm việc cho các loại cơ bản như số và chuỗi (giả sử chúng không cần phải thoát) nhưng đối với mảng, đối tượng giống như băm và loại tùy chỉnh, tôi phải viết một trường hợp đặc biệt cho mỗi loại và tiếp tục chỉnh sửa khi tôi yêu cầu nhiều vật thể hơn hoặc ít hơn. – DanielB

+0

Trong trường hợp đó, bạn có thể viết một hàm 'toRuby()' duy nhất và cho nó biết cách chuyển đổi đối tượng đã truyền, ví dụ: 'toRuby (someFn, 'fn')', 'toRuby (someObj, 'obj')' hoặc tương tự. – RobG

+0

Đó là những gì tôi ban đầu có, nhưng khi số lượng các loại đối tượng có thể tăng lên, tôi đã thấy nó sẽ dễ dàng hơn khi có phương thức to_ruby trên các đối tượng hỗ trợ chuyển đổi. Bằng cách đó tôi có thể dễ dàng kiểm tra hỗ trợ cũng như thực hiện chuyển đổi. – DanielB

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