2012-04-26 32 views
10
var someObj = function() { } 
var p = new someObj(); 

alert(someObj.prototype); // This works 
alert(p.prototype);   // UNDEFINED, but why? 

someObj.prototype.model= "Nissan"; 
alert(p.model);    // This works! I understand the dynamic nature of prototypes, but doesn't that mean that p.prototype === someObj.prototype? 

Tại sao lại như vậy? Vì "p" là một thể hiện của "someObj", tại sao nguyên mẫu không xác định? Tôi có nghĩa là, khi tôi thêm một tài sản để "someObj" nguyên mẫu, nó có thể truy cập đến "p", vậy tại sao nguyên mẫu không thể truy cập?Nguyên mẫu Javascript thông qua Object.create()

Trả lời

11

Điều quan trọng ở đây là thuộc tính prototype của đối tượng hàm không phải là nguyên mẫu của đối tượng. Đó là đối tượng sẽ được gán làm nguyên mẫu của đối tượng bạn tạo thông qua new someObj. Trước ES5, bạn không thể truy cập trực tiếp nguyên mẫu của một đối tượng; kể từ ES5, bạn có thể, thông qua Object.getPrototypeOf.

Re

alert(p.prototype); // UNDEFINED, but why?

Lý do là đối tượng p không có một tài sản được gọi là "nguyên mẫu". Nó có một nguyên mẫu cơ bản, nhưng đó không phải là cách bạn truy cập nó.

Tất cả đối tượng hàm có thuộc tính được gọi là prototype để nếu chúng được sử dụng làm hàm dựng, chúng ta có thể xác định những thuộc tính của nguyên mẫu cơ bản của đối tượng được tạo bởi các hàm tạo đó sẽ là gì. Điều này có thể giúp:

function Foo() { 
} 
Foo.prototype.answer = 42; 

console.log(Foo.prototype.answer); // "42" 
var f = new Foo(); 
console.log(f.answer); // "42" 

Đó dòng cuối cùng làm việc như thế này:

  1. Lấy đối tượng f.
  2. friêng của mình thuộc tính được gọi là "trả lời" không?
  3. Không, không f có mẫu thử nghiệm không?
  4. Có, nguyên mẫu có riêng thuộc tính được gọi là "trả lời" không?
  5. Có, trả về giá trị của thuộc tính đó.

Bạn đã đề cập Object.create trong tiêu đề câu hỏi của mình. Điều quan trọng là phải hiểu rằng Object.create hoàn toàn tách biệt với các hàm dựng. Nó đã được thêm vào ngôn ngữ để nếu bạn không thích sử dụng hàm xây dựng, bạn không phải, nhưng vẫn có thể thiết lập nguyên mẫu của đối tượng   — trực tiếp, khi bạn tạo đối tượng đó.

+0

Giải thích tuyệt vời –

+0

@TahaAhmad: Rất vui được giúp! –

2

p.prototype không hoạt động vì trong trường hợp này p = someObj.prototype.

Về cơ bản khi bạn sử dụng toán tử mới, điều gì xảy ra là hàm tạo someObj được sử dụng để khởi tạo một đối tượng mới. Có nghĩa là nó trả về một đối tượng có thuộc tính và phương thức của nguyên mẫu của hàm tạo.

Do đó p = someObj.prototype và p.prototype không được xác định là p không phải là hàm tạo.

Bài viết này có thể giúp giải thích điều này hơn

http://www.htmlgoodies.com/html5/tutorials/javascript-prototypical-inheritance-explained.html#fbid=A2ikc3JLxeD

+0

Câu trả lời của mỗi Crowder, nguyên mẫu là có và có thể truy cập, thông qua việc sử dụng Object.getPrototypeOf (p). Nếu sự hiểu biết của tôi là chính xác, rằng các thuộc tính và phương thức được sao chép vào các cá thể đối tượng mới, nhưng điều đó không có nghĩa là p === someObj.prototype. Nó có nghĩa là p.prototype === someObj.prototype –

1

p là một dụ của someObj. Nguyên mẫu thuộc về hàm tạo. Bạn có thể lấy mẫu thử nghiệm hàm tạo của p bằng cách sử dụng p.constructor.prototype

6

Đó là vì thuộc tính của hàm tạo, chứ không phải là thuộc tính của chính nó. Tuy nhiên, đối tượng prototype có một tham chiếu đến các nhà xây dựng, vì vậy bạn có thể truy cập vào một của prototype đối tượng qua constructor tài sản của mình:

function Foo() {} 

Foo.prototype.foo = "bar"; 

var c = new Foo; 

console.log(c.constructor === Foo); // true 
console.log(c.constructor.prototype); // { foo: 'bar' } 

Tuy nhiên, điều này sẽ không hoạt động nếu bạn ghi đè lên ban đầu prototype tài sản của hàm constructor:

function Foo() {} 

// I overwrite the prototype property, so I lose the initial reference 
// to the constructor. 
Foo.prototype = { 
    foo: "bar" 
}; 

var c = new Foo; 

console.log(c.constructor === Foo); // false 
console.log(c.constructor === Object); // true 
console.log(c.constructor.prototype); // {} 

Đó là lý do tại sao bạn nên sử dụng phương pháp Object.getPrototypeOf mới được giới thiệu trong ES5.

function Foo() {} 

Foo.prototype = { 
    foo: "bar" 
}; 

var c = new Foo; 

console.log(c.constructor === Foo); // false 
console.log(c.constructor === Object); // true 
console.log(c.constructor.prototype); // {} 
console.log(Object.getPrototypeOf(c)); // { foo: 'bar' } 

Một giải pháp khác có thể đã được để đảm bảo bạn khôi phục lại các tài liệu tham khảo constructor trên nguyên mẫu:

function Foo() {} 

// Overwriting the initial prototype  
Foo.prototype = { 
    constructor: Foo, // restore the constructor reference 
    foo: "bar" 
}; 
+0

Tôi tìm thấy một blogpost cực kỳ hữu ích, kết hợp với câu trả lời này, xóa rất nhiều sự nhầm lẫn về toàn bộ sự điên rồ nguyên mẫu. http://blog.sklambert.com/javascript-prototype/ các sơ đồ giúp ích rất nhiều trong việc hiểu câu trả lời này. Hy vọng điều này sẽ giúp một ai đó. – Bruce

0

Trong javascript, nhà thầu, và trong thực tế tất cả các chức năng có được một thuộc tính prototype. Một đối tượng (có nghĩa là, một tập hợp các cặp khóa-giá trị), không có thuộc tính mẫu thử nghiệm. Trong ví dụ của bạn ở trên,

var someObj = function() { } // this is a function, so it has a prototype property 
var p = new someObj(); // this is an instance object, so it doesn't 

Đó là lý do tại sao someObj.prototype được định nghĩa nhưng p.prototype thì không.

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