簡體   English   中英

通過Object.create()的Javascript原型

[英]Javascript prototype through Object.create()

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?

為什么會這樣? 由於“p”是“someObj”的一個實例,為什么原型未定義? 我的意思是,當我向“someObj”原型添加屬性時,它可以被“p”訪問,那么為什么原型不可訪問?

這里重要的是函數對象的prototype屬性不是對象的原型。 這個對象將被指定為您通過new someObj創建的對象的原型。 在ES5之前,您無法直接訪問對象的原型; 從ES5開始,您可以通過Object.getPrototypeOf

回覆

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

原因是p對象沒有名為“prototype”的屬性。 它有一個底層原型,但這不是你訪問它的方式。

所有函數對象都有一個名為prototype的屬性,這樣如果它們被用作構造函數,我們就可以定義這些構造函數創建的對象的底層原型的屬性。 這可能有所幫助:

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

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

最后一行是這樣的:

  1. 獲取f對象。
  2. f自己的屬性叫做“回答”嗎?
  3. 不,不f有原型?
  4. 是的,原型是否有自己的屬性叫做“回答”?
  5. 是的,返回該屬性的值。

你在問題的標題中提到過Object.create 理解Object.create與構造函數完全分離很重要。 它被添加到語言中,因此如果您不希望使用構造函數,則不必使用,但仍可以在創建該對象時直接設置對象的原型。

那是因為prototype是構造函數的屬性,而不是它自身的屬性。 但是, prototype對象具有對構造函數的引用,因此您可以通過其constructor屬性訪問對象的prototype

function Foo() {}

Foo.prototype.foo = "bar";

var c = new Foo;

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

但是,如果覆蓋構造函數的初始prototype屬性,這將不起作用:

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 );  // {}

這就是為什么你最好使用ES5中引入的新Object.getPrototypeOf方法。

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' }

另一種解決方案是確保恢復原型上的constructor引用:

function Foo() {}

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

p.prototype不起作用,因為在這種情況下p = someObj.prototype。

基本上當你使用new運算符時,發生的是構造函數someObj用於初始化一個新對象。 這意味着它返回一個對象,該對象具有構造函數原型的屬性和方法。

因此p = someObj.prototype和p.prototype是未定義的,因為p不是構造函數。

本文可能有助於解釋這一點

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

psomeObj一個實例 原型屬於構造函數。 您可以使用p.constructor.prototype檢索p的構造函數原型

在Javascript,構造函數中,實際上所有函數都獲得了一個prototype屬性。 對象(即一組鍵值對)沒有prototype屬性。 在上面的例子中,

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

這就是為什么someObj.prototype被定義,但p.prototype不是。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM