2010-02-11 32 views
17

Với đoạn mã sau:Làm cách nào tôi có thể thấy chuỗi nguyên mẫu của đối tượng Javascript?

function a() {} 
function b() {} 
b.prototype = new a(); 
var b1 = new b(); 

Chúng tôi có thể ở lại đó a đã được thêm vào b 's chuỗi nguyên mẫu. Tuyệt quá. Và, tất cả những điều sau đây là đúng:

b1 instanceof b 
b1 instanceof a 
b1 instanceof Object 

Câu hỏi của tôi là, nếu chúng ta không biết nguồn gốc của b1 trước thời hạn? Làm thế nào chúng ta có thể khám phá các thành viên của chuỗi nguyên mẫu của nó? Lý tưởng nhất là tôi muốn một mảng như [b, a, Object] hoặc ["b", "a", "Object"].

Điều này có khả thi không? Tôi tin rằng tôi đã nhìn thấy một câu trả lời ở đâu đó trên SO mô tả làm thế nào để tìm ra chỉ này, nhưng tôi không thể cho cuộc sống của tôi tìm thấy nó một lần nữa.

Trả lời

2

Bạn có thể sử dụng thuộc tính "constructor" của đối tượng để tìm nguyên mẫu ở đó và sau đó chuỗi dọc theo đó cho đến khi bạn đến cuối cầu vồng.

function getPrototypes(o) { 
    return (function gp(o, protos) { 
    var c = o.constructor; 
    if (c.prototype) { 
     protos.push(c.prototype); 
     return gp(c.prototype, protos); 
    } 
    return protos; 
    })(o, []); 
} 

(có thể) (hoặc có thể không :-) cho tôi một giây) (cũng tào lao, tôi nghĩ rằng nó có thể bỏ qua nhưng mã)

[sửa] wow này là hoàn toàn thổi tâm trí của tôi - chức năng đó gần nhưng không hoàn toàn đúng; thiết lập một chuỗi các nguyên mẫu là lạ và tôi cảm thấy sợ hãi và cô đơn. Tôi đề nghị chỉ chú ý đến các @CMS tuyệt vời ở trên.

+0

'hàm tạo' cung cấp cho bạn chức năng hàm tạo của tổ tiên nguyên mẫu gần nhất mà không được kế thừa từ một nguyên mẫu xây dựng khác. Điều này gần như không bao giờ những gì bạn muốn. Ví dụ trong mã của câu hỏi, 'b1.constructor' là' a', không phải 'b', và nếu bạn bắt nguồn một đối tượng' c' từ 'b',' c1.constructor' sẽ vẫn là 'a'. Quy tắc bình thường của ngón tay cái: Không sử dụng 'constructor' cho bất cứ điều gì bao giờ hết. [eta: lol @ 'sợ hãi và cô đơn' ... vâng, đây là một trong những phần của JavaScript được thiết kế để gây nhầm lẫn cho bạn bằng cách làm một cái gì đó có vẻ hữu ích nhưng thực sự là một cái bẫy.] – bobince

+0

Vâng, tôi xem xét câu hỏi ban đầu một bài tập thú vị nhưng nó không bao giờ là cái gì tôi muốn đưa vào mã mà tôi mong đợi để thực sự làm việc. Có một lời giải thích thực sự tốt đẹp ở đây: http://mckoss.com/jscript/object.htm – Pointy

7

Vâng, liên kết mẫu thử giữa các đối tượng ([[Prototype]]) là nội bộ, một số triển khai, như Mozilla, hiển thị nó dưới dạng obj.__proto__.

Phương pháp Object.getPrototypeOf của Ấn bản ECMAScript lần thứ 5 là những gì bạn cần, nhưng hiện chưa được triển khai trên hầu hết các công cụ JavaScript.

tặng một cái nhìn đến này implementation bởi John Resig, nó có một cái bẫy, nó dựa trên constructor tài sản của động cơ không hỗ trợ __proto__:

if (typeof Object.getPrototypeOf !== "function") { 
    if (typeof "test".__proto__ === "object") { 
    Object.getPrototypeOf = function(object){ 
     return object.__proto__; 
    }; 
    } else { 
    Object.getPrototypeOf = function(object){ 
     // May break if the constructor has been tampered with 
     return object.constructor.prototype; 
    }; 
    } 
} 

Hãy nhớ rằng đây không phải là 100% đáng tin cậy, vì thuộc tính constructor có thể thay đổi được trên bất kỳ đối tượng nào.

+2

giống như bất cứ điều gì trong Javascript nhìn vào tài sản đối tượng và tin tưởng những gì bạn nhận được là nguy hiểm :-) – Pointy

+0

Cảm ơn, nhưng điều đó nói với tôi rằng 'a' là một nguyên mẫu của' b1' nhưng không có gì về 'b'. Làm thế nào tôi có thể thấy rằng 'b1' là một thể hiện của' b'? – pr1001

+0

Quay trở lại 'constructor' không chỉ là sai bởi vì giả mạo tiềm năng giả mạo, nó hoàn toàn sai khi bắt đầu bởi vì' constructor' không làm những gì bạn nghĩ nó sẽ (xem bình luận bên dưới). Điều này cho thấy một sự thiếu hiểu biết đáng ngạc nhiên về chức năng JavaScript cơ bản từ Resig; ** không ** sử dụng tập lệnh này. Tuy nhiên, thông tin về '__proto__' và' getPrototypeOf' là tốt. – bobince

0

Đây là một điểm khởi đầu:

Object.prototype.getConstructorNames=function(){ 
     return Object.keys(window).filter(function(e){ 
      return typeof window[e]==="function" && this instanceof window[e]},this) 
    } 

Tất nhiên điều này là thực sự không đầy đủ nhưng tôi nghĩ rằng nó sẽ làm việc trong hầu hết các trường hợp và nếu có ai muốn thêm vào đó họ có thể.

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