2015-04-30 11 views
6

Tôi muốn thử theo cách thủ công khi đi bộ chuỗi nguyên mẫu của một vài đối tượng chỉ để xem những gì tôi tìm thấy trên đường đi. Tuy nhiên, tôi đã bị mắc kẹt trên cái đầu tiên mà tôi đã thử. Dưới đây là các mã:Khó đi theo cách thủ công Chuỗi thử nghiệm

function MyObject() { } 
var x = new MyObject(); 
console.log('--------------------------------------------'); 
console.log('x.constructor.name: ' + x.constructor.name); 
console.log('x.constructor.prototype.constructor.name: ' + x.constructor.prototype.constructor.name); 
console.log(x.constructor.prototype === Function.prototype ? 'Good guess.' : 'No, you are wrong.'); 
console.log(x.constructor === MyObject ? 'Good guess.' : 'No, you are wrong.'); 
console.log('--------------------------------------------'); 

Kết quả mã trên trong đầu ra sau trong Công cụ nhà phát triển điều khiển của Google Chrome:

-------------------------------------------- 
x.constructor.name: MyObject 
x.constructor.prototype.constructor.name: MyObject 
No, you are wrong. 
Good guess. 
-------------------------------------------- 

Nó làm cho cảm giác rằng constructor x là chức năng MyObject, vì x được khởi tạo sử dụng từ khóa mới trên MyObject (từ này theo định nghĩa của hàm tạo). Bởi vì điều này, tôi hiểu dòng đầu tiên của đầu ra (lưu ý: tôi bắt đầu đếm dòng đầu ra từ số không lên). Tuy nhiên, dòng thứ hai làm tôi bối rối. Tôi muốn biết nguyên mẫu của MyObject là gì. Rõ ràng, nó không phải là một đối tượng của chức năng loại, như được chỉ ra bởi dòng thứ 3 của đầu ra, mà nói với tôi rằng tôi là sai. Dòng đầu ra thứ tư chỉ củng cố đầu ra từ dòng đầu tiên. Trên một lưu ý chung hơn, tôi giả định rằng cách chính xác để đi bộ chuỗi nguyên mẫu của một đối tượng sẽ là đi từ đối tượng trong câu hỏi đến constructor của nó, và sau đó từ constructor đến prototype của constructor, giả định rằng điều này tham chiếu cuối cùng không phải là null. Tôi giả định rằng quá trình hai bước này (bao gồm việc đi tới hàm khởi tạo, và sau đó đến nguyên mẫu của hàm tạo) nên được lặp lại cho đến khi một tham chiếu null từ một hàm tạo đến một mẫu thử nghiệm đạt được, do đó biểu thị sự kết thúc của chuỗi nguyên mẫu. Điều này dường như không được làm việc, mặc dù, kể từ khi áp dụng thuật toán này cho kịch bản trên chỉ dẫn đến tham chiếu vòng tròn.

Nói tóm lại, tôi có hai câu hỏi:

  1. Tại sao x.constructor === x.constructor.prototype.constructor (hoặc, nói cách khác, tại sao các tài liệu tham khảo hình tròn), và những loại một đối tượng là x.constructor.prototype, dù sao (hoặc, nói cách khác, làm thế nào nó có được instantiated/nó đã đến từ đâu)?
  2. Làm cách nào để thuật toán trên có thể được sửa lại để đi đúng chuỗi nguyên mẫu cho đối tượng x?

Sửa

Tôi đã xem qua một câu hỏi tương tự trên StackOverflow here, nhưng nó không explicity hỏi cách chính xác để đi bộ chuỗi nguyên mẫu. Nó chỉ ra các tham chiếu vòng tròn, mặc dù ...

Trả lời

3

Trong thuật ngữ Javascript, một đối tượng a 's 'nguyên mẫu' dùng để chỉ đối tượng mà từ đó a được thừa hưởng tài sản. Cách dựa trên tiêu chuẩn để truy cập này là với Object.getPrototypeOf:

var protoOfA = Object.getPrototypeOf(a); 

Ngoài ra còn có những cách cũ, không đúng tiêu chuẩn nhưng được hỗ trợ bởi một số trình duyệt:

var protoOfA = a.__proto__; 

Nhưng nếu bạn có một hàm F, F.prototype KHÔNG tham chiếu đối tượng mà từ đó F thừa kế bất kỳ thứ gì. Thay vào đó, nó đề cập đến đối tượng mà từ đó trường tạo ra bởi F kế thừa:

function F() {}; 
a = new F(); 
console.log(Object.getPrototypeOf(a) === F.prototype); // true 

Khi bạn xác định một chức năng, một đối tượng được tạo ra để phục vụ như là nguyên mẫu của trường tạo ra bởi chức năng đó, và đối tượng mới này được lưu trữ trong thuộc tính prototype của hàm.

-

Chức năng hoạt động giống như các đối tượng trong nhiều cách (ví dụ, họ có thể có tài sản) nhưng họ không chính xác như các đối tượng khác:

console.log(typeof a); // "object" 
console.log(typeof F); // "function" 

"nguyên mẫu" của họ là ill- định nghĩa (ví dụ chạy trong Chrome) (điều này rõ ràng là một Chrome-specific behavior)

console.log(Object.getPrototypeOf(F)); // "function Empty() {}" 
console.log(Empty);     // ReferenceError: Empty is not defined 

-

012.

Thuộc tính constructor lạ. The interpreter doesn't care about it. MDN says, confusingly:

Trả về tham chiếu đến hàm Đối tượng đã tạo mẫu thử của cá thể.

Hơn nữa, bạn có thể thay đổi giá trị constructor trên một đối tượng, nhưng điều này không ảnh hưởng đến đối tượng hoặc hành vi của đối tượng - nó chỉ mang tính mô tả.

-

Vì vậy, để giải đáp thắc mắc của bạn:

Tại sao x.constructor === x.constructor.prototype.constructor

Không lý do chính đáng. Đây là các trình duyệt hành vi tùy ý đã hội tụ.

loại một đối tượng là x.constructor.prototype, dù sao

Trong ví dụ này, nguyên mẫu x 's t của, giống như Object.getPrototypeOf(x).Nhưng nói chung bạn không thể dựa vào x.constructor hoặc bất cứ thứ gì bắt nguồn từ nó, bởi vì nó tùy ý.

Làm cách nào để thuật toán trên có thể được sửa lại để đi đúng chuỗi nguyên mẫu cho đối tượng x?

for (var p = x ; p != null ; p = Object.getPrototypeOf(p)) { 
    // do something with p 
} 
1

Vâng, điều này có thể hơi khó nắm bắt lúc đầu. Tôi không thể làm tốt hơn cung cấp cho bạn một số liên kết. Những thứ này luôn giúp tôi khi tôi gặp rắc rối.

http://dmitrysoshnikov.com/ecmascript/javascript-the-core/

http://mckoss.com/jscript/object.htm

http://zeekat.nl/articles/constructors-considered-mildly-confusing.html

Q1: Đối với "tại sao" nhìn thấy tài liệu tham khảo ở trên. x.constructor.prototypex.__proto__ đó là nguyên mẫu "thực" bên trong của x, ít nhất là trong trường hợp của bạn khi không có các thuộc tính prototypeconstructor bị ghi đè. Nó được tạo ra khi bạn định nghĩa hàm MyObject.

Q2: Rất tiếc, bạn không thể thực hiện theo cách này.Bạn có thể sử dụng tài sản __proto__ nơi nó được hỗ trợ, nhưng thấy

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto

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