JS對象中的構造函數和實例原型不一樣嗎?

function OMakeNewCar(){

}

var car = new OMakeNewCar;

OMakeNewCar是構造函數

其中,OMakeNewCar.prototype指向實例原型,但是它具體到底是什麼呢?是Function對象,還是Object對象?我測試時這樣輸:

OMakeNewCar.prototype.mm = 1;

alert(Function.mm);//undefined

alert Object.mm得到的提示一樣,不過如果輸 alert(OMakeNewCar.prototype.mm),輸出1,說明賦值以後它還是在內存中的,但是 OMakeNewCar的原型既不是Function對象也不是Object對象,它到底是什麼?

car是構造函數 OMakeNewCar 的實例,為什麼car.prototype指向的不是構造函數?

謝謝!


我想,題主對於構造函數和原型對象的概念理解的還不夠透徹。

所謂構造函數,是生成一個對象的模板,是生成對象的函數。一個構造函數,可以生成多個實例對象,每個實例對象都有相同的結構。

接以上的例子,當你使用new操作符調用Keith構造函數時,會經歷以下步驟:

1.創建一個空對象,作為將要返回的實例對象

2.將空對象的原型指向構造函數的prototype屬性,也就是Keith構造函數的prototype屬性。

3.將空對象賦值給構造函數內部的this關鍵字,也就是this關鍵字會指向實例對象。

4.開始執行構造函數內部的代碼。

題主的第一個問題是,Keith.prototype指向實例原型,但是它具體指向什麼?

題主可能理解錯誤了。正確的邏輯應該是:

person1實例對象的原型指向了Keith.prototype。

Keith的原型指向了Function.prototype。

Function.prototype的原型指向了Object.prototype。

Object.prototype的原型指向了Null。

當然了,person2實例對象也是如此。

所以,題主所說的構造函數的原型 Keith.prototype指向的不是Function,也不是Object,而是Object.prototype。

另外。當為構造函數定義原型屬性,並且訪問原型屬性時,

因為mm是原型Keith.prototype上定義的一個屬性。Function對象沒有定義mm屬性,所以返回了默認值undefined。

但是這樣訪問一個原型屬性是沒有意義的。而是應該通過對象實例來訪問原型屬性。

person1實例對象本身是沒有mm屬性的,所以會在原型Keith.protoype上查找。在原型找到了mm屬性,所以就繼承了原型的mm屬性。若原型上沒有mm屬性,會繼續在原型的原型上查找,直到null對象,若還是沒有該屬性,則返回undefined。

回答題主的最後一個問題:car是構造函數 OMakeNewCar 的實例,為什麼car.prototype指向的不是構造函數?

從例子上面的說明,我想題主應該知道原因了。構造函數只是提供創建對象的模板,而不是原型對象。所以person1.prototype指向的不是構造函數,而是構造函數的原型。

希望題主能明白。

謝謝。

個人博客:Uncle-Keith - 博客園


1、OMakeNewCar.prototype 指向構造函數 OMakeNewCar 自身的原型對象。

要理解這一點,樓主需要先了解一些東西。

每在屏幕上敲出來一個函數,啥構造不構造的,根本不用管,系統都會為這個函數創建一個 prototype 屬性。這個 prototype 屬性指向一個對象,這個對象就是此函數的原型對象。

原型對象哪來的,系統分配的唄,當然這裡要注意一點,原型對象可不是 Function 或 Object,而是系統會為每個函數創建屬於它自己的原型對象,因此每個函數的原型對象都是不同的。

那原型對象里都有啥,其實很簡單,如果你不操作這個原型對象,那麼一開始它只包含一個屬性:constructor。當然可以在原型對象上添加你想添加的任何屬性。

constructor 屬性幹啥用的?指向函數自身。

回到問題,OMakeNewCar.prototype 指向的就是函數 OMakeNewCar 的原型對象。

如果想看看此時 OMakeNewCar 原型對象中的 constructor 屬性,可以這樣寫 OMakeNewCar.prototype.constructor,樓主可以想到 OMakeNewCar.prototype.constructor 就是 function OMakeNewCar() {}。

2、car 是構造函數 OMakeNewCar 的實例,但 car 沒有 prototype 屬性。

樓主還是需要先了解以下的東西。

只有函數才有 prototype 屬性,其他對象均沒有此屬性。樓主一定會問,那 car 不是函數嗎,答案是 car 不是函數,而只是一個普通對象。

簡單解釋一下 var car = new OMakeNewCar(); 這段代碼。

先看等號右邊 new OMakeNewCar(),別管什麼 new 不 new 的,這不過就是在調用 OMakeNewCar 這個函數,函數調用後都有返回值(沒有明確返回值的函數,返回值是undefined)。那函數前面加了 new 調用,返回值是啥呢?解決樓主問題的關鍵點來了,返回值是一個對象。

再看等號的左邊,從函數中返回的對象被賦值給了 car。因此,此時的 car 就代表了返回的對象。car 代表的對象只是一個普通對象,所以沒有 prototype屬性。

這裡需要插句話,樓主為了測試加了這樣一句代碼 OMakeNewCar.prototype.mm = 1;也就是在構造函數原型上加了 mm 這個屬性,並把 1 賦值給了這個屬性。

可以告訴樓主,下面我寫的這句代碼也是可以正確運行的

alert(car.mm); // 彈出 1

接下來,需要跟樓主介紹任何對象上的都有的一個屬性,叫做 __proto__,跟函數上的 prototype 屬性有點像,沒錯,確實有點像。

這個屬性幹嘛用的?指向該對象構造函數上的原型對象,即和構造函數的 Prototype 屬性指向的是同一個對象。

回到問題,car 的構造函數是 OMakeNewCar,那麼 car.__proto__ 指向的就是 OMakeNewCar 的原型對象。

看看下面的這兩句代碼

OMakeNewCar.prototype.mm = 1;

alert(car.mm);

mm 屬性 car 對象上原本沒有,但其構造函數的原型對象上有,所以在 car 上找不到 mm 時,系統就會通過 __proto__ 找到其構造函數的原型對象,然後找到了 mm 屬性。

當然實際寫代碼時不要加 __proto__ 屬性,直接寫 car.mm 就行,如果在 car 對象中找不到 mm,系統就會自動到其構造函數的原型對象上去找。


car是實例對象,沒有prototype這個引用屬性。想要訪問他的構造函數的原型

可以car.__proto__.mm =xxx來賦值,構造函數中的原型對象是繼承Object.prototype的

(構造函數)__proto__ === Object.prototype,對象構造函數的prototype 是終點,

Object.prototype.__proto__ === null。

因為Object是構造函數,Object.__proto__指向Function.prototype,Function.prototype.__proto__ === Object.prototype

Function.__proto__ === Function.prototype

Object.prototype才是JS中的爸爸。


這是js下的一個大坑呀

推薦查閱下這個網址JS原型與原型鏈終極詳解

而且car是由OMakeNewCar 實例化而來,並非構造函數,不存在prototype屬性!


推薦閱讀:

如何有效快速的學習HTML/CSS/JS?
都說學習原生 JS 很重要,在實際網站前台應用開發中哪些是 jQuery 這些庫無法解決的?
h5 css js學習時間加起來大概需要多少時間,推薦幾個網上學習課程?
自己寫HTML用Cordova打包與用AppCan、Dcloud、WeX5、ApiCloud有何區別?
你為什麼選擇做前端?

TAG:HTML | JavaScript | ECMAScript |