Javascript中的prototype proto和constructor

主要結論:

只有函數對象有prototype原型屬性,而且函數對象的原型(prototype)指向該函數對象的實例對象

任何對象都有__proto__屬性,也可稱為隱式原型,而且一個對象的隱式原型指向構建該對象的構造函數的原型prototype

任何對象都有constructor屬性,而且一個對象的constructor屬性指向創建該對象的構造函數。


1. 除了JSON和Math, js中所有的內置對象(如Number, String, Array, Error, RegExp, Object, Boolean, Date, Event)typeof都是function, json和math是object.

2.__proto__是隱藏屬性,不管是普通對象還是函數對象都有該屬性. 所有的對象的obj都具有proto屬性(null和undefined除外),可稱為隱式原型。一個對象的隱式原型指向構造該對象的構造函數的原型,即為函數對象的prototype屬性。如下圖


Object.__proto__ ===> function (){}

Date.__proto__ ===> function (){}

Error.__proto__ ===> function (){}

RegExp.__proto__===> function (){}

Number.__proto__ ===> function (){}

String.__proto__ ===> function (){}
Boolean.__proto__ ===> function (){}

Array.__proto__ ===> function (){}

然而這些內置對象的實現則指向相應的內置對象,如:

str1.__proto__ ====> String

arr1__proto__ ====> []

n1__proto__ ====> Number

bl1__proto__ ====> Boolean

但是Error,Date 和 Object的實現指向Object

============================================

Object.prototype ===> Object{ }

Date.prototype ===> Object{ }

Error.prototype ===> Object{ }

RegExp.prototype===> Object{}

Event.prototype===> Object{}

Number.prototype===> Number{ }

String.prototype ===> String{ }

Boolean.prototype ===>Boolean{ }

Array.prototype ===> [ ]

Function.prototype ===> function(){}

然而這些內置對象的實現則指向相應的內置對象,如:

str1.__proto__ ====> String

arr1__proto__ ====> []

n1__proto__ ====> Number

bl1__proto__ ====> Boolean

也就是說,每個內置對象的__protot


3.prototype是顯式原型,只有函數對象才有,即以function創建的

function a () {};

var obj = new a();

a.prototype = new Object();

a.prototype = obj; 因此一個函數對象a的prototype 屬性指向的是該函數對象a的實例對象obj。

4.所有對象的實例是沒有prototype屬性的(不管是new方式創建的還是對象字面量的方式創建的)

5.一個對象的constructor指向創建它的對象,如下圖


說到prototype,就不得不先說下new的過程。

我們先看看這樣一段代碼:

var Person =function() { };

var p =new Person();

很簡單的一段代碼,我們來看看這個new究竟做了什么?我們可以把new的過程拆分成以下三步:

<1> var p={}; 也就是說,初始化一個對象p。

Person.prototype = new Object();

Person.prototype = p;

<2> p.__proto__=Person.prototype;

<3> Person.call(p);也就是說構造p,也可以稱之為初始化p。

關鍵在于第二步,我們來證明一下:

var Person =function() { };

var p =new Person();

alert(p.__proto__ === Person.prototype);

這段代碼會返回true。說明我們步驟2的正確。

那么__proto__是什么?我們在這里簡單地說下。每個對象都會在其內部初始化一個屬性,就是__proto__,當我們訪問一個對象的屬性

時,如果這個對象內部不存在這個屬性,那么他就會去__proto__里找這個屬性,這個__proto__又會有自己的__proto__,于是就這樣

一直找下去,也就是我們平時所說的原型鏈的概念。



在 ECMAScript 中,所有對象并非同等創建的。

一般來說,可以創建并使用的對象有三種:本地對象、內置對象和宿主對象。

本地對象

ECMA-262 把本地對象(native object)定義為“獨立于宿主環境的 ECMAScript 實現提供的對象”。簡單來說,本地對象就是 ECMA-262 定義的類(引用類型)。它們包括:

Object

Function

Array

String

Boolean

Number

Date

RegExp

Error

EvalError

RangeError

ReferenceError

SyntaxError

TypeError

URIError

相關頁面

JavaScript 高級教程:ECMAScript 引用類型

JavaScript 高級教程:ECMAScript Function 類

JavaScript 參考手冊:Array 對象

JavaScript 參考手冊:Boolean 對象

JavaScript 參考手冊:Date 對象

JavaScript 參考手冊:Number 對象

JavaScript 參考手冊:String 對象

JavaScript 參考手冊:RegExp 對象

內置對象

ECMA-262 把內置對象(built-in object)定義為“由 ECMAScript 實現提供的、獨立于宿主環境的所有對象,在

ECMAScript 程序開始執行時出現”。這意味著開發者不必明確實例化內置對象,它已被實例化了。ECMA-262 只定義了兩個內置對象,即

Global 和 Math (它們也是本地對象,根據定義,每個內置對象都是本地對象)。

相關頁面

JavaScript 參考手冊:Global 對象

JavaScript 參考手冊:Math 對象

宿主對象

所有非本地對象都是宿主對象(host object),即由 ECMAScript 實現的宿主環境提供的對象。

所有 BOM 和 DOM 對象都是宿主對象。

相關頁面

JavaScript 高級教程:JavaScript 實現

W3School 參考手冊:JavaScript 參考手冊

W3School 教程:HTML DOM 教程

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容