主要結論:
只有函數對象有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 教程