文章同步地址 : 編程愛好者協會javascript
這篇文章旨在用最簡單的語言告訴你什麼是原型對象以及什麼是原型鏈。java
全部的數據類型(除了 null
和 undefined
)都有 contructor
構造函數,但只有 函數 纔有 prototype
屬性:編程
/* 數值類型 ---------------------*/
var num = NaN;
num.constructor // function Number()
num.prototype // undefined
/* 布爾類型 ---------------------*/
var boo = true;
boo.constructor // function Boolean()
boo.prototype // undefined
/* 字符串類型 ---------------------*/
var str = 'string';
str.constructor // function String()
str.prototype // undefined
/* undefined ---------------------*/
var undefine = undefined;
undefine.constructor // TypeError
undefine.prototype // TypeError
/* null ---------------------*/
var nul = null;
nul.constructor // TypeError
nul.prototype // TypeError
/* function ---------------------*/
var fn = function() {};
fn.contructor // function fn()
fn.prototype // Object
複製代碼
這下知道爲啥別人說 null
和 undefined
是特殊的數據類型了吧!也知道爲啥別人說函數是特殊的對象了是否是?這也是爲啥有人說 函數是一等公民 的緣由,正是由於函數具備 prototype
屬性使它擁有了無限的擴展性。設計模式
prototype
指向一個包含 constructor
屬性的對象。說白了,就是 prototype
是一個對象,具備 constructor
屬性,也是一個對象。該 contructor
屬性值爲對象自己:瀏覽器
Function.prototype.constructor === Function
// true
複製代碼
我懷疑 JS 做者當初只是想經過 prototype.constructor
來描述一個方法的構造函數就是它自己。而其它語言的構造函數,如 Java, 只是一個與類同名的函數。bash
__proto__
和 prototype
的關係__proto__
實際上是 ECMAScript 標準 [[Prototype]]
的代理實現,是各瀏覽器提供的,檢查瀏覽器是否支持此屬性能夠使用 Object.getPrototypeOf({__proto__: null}) === null
。函數
__proto__
指向對象的構造函數的 prototype
ui
window.__proto__ === window.constructor.prototype
// true
複製代碼
上面說全部的數據類型都有構造函數並不許確或者說是不夠精細。當咱們建立一個空對象的時候你會發現這個空對象並不 「空」:spa
var object = new Object();
object.constructor
// function Object()
複製代碼
既然是 「空」 對象,爲何還會有 constructor
屬性呢?prototype
嗯,這個時候再引入 __proto__
應該會把事情搞明白。其實這裏的 object.constructor
應該是 object.__proto__.constructor
,因此 constructor
其實並非內部屬性。:
object.constructor === object.__proto__.constructor
// true
複製代碼
而前面說過 __proto__
指向的是對象構造函數的 prototype
,那麼這裏的 constructor
是否是就是其對象構造函數下的 prototype.constructor
呢?答案是:bingo
var object = new Object();
object.constructor === Object.prototype.constructor
// true
複製代碼
因此 __proto__
的做用是,當訪問一個對象的屬性時,若是該屬性不直接存在對象上,則會去其 __proto__
所指向的對象裏去找,若是不存在就會一直找下去,直到 __proto__
值爲 null
。
prototype
的做用又是什麼呢?簡單來講,就是共享屬性和方法。
new
關鍵字常常會被使用,但但是你知道何時才須要 new
嗎?是的,很簡單判斷。若是你將要調用的屬性或方法是屬於調用對象的 prototype
的,那麼在使用它以前你須要先實例化這個對象。
var Person = function() {};
Person.name = 'Fish Chan';
Person.prototype.sayHello = function() {
console.log('雷吼呀!');
};
// 不須要 new 就能夠使用的屬性
Person.name // Fish Chan
// 必須 new 才能使用的屬性
Person.sayHello(); // TypeError
var boy = new Person();
boy.sayHello(); // 雷吼呀!
複製代碼
學完 JavaScript 中的原型和原型鏈後再去學 JavaScript 中的面向對象和設計模式一定會輕車熟路。因爲篇幅有限,後面再細講如何模仿面嚮對象語言和如何開發設計模式。
本文做者懶得畫圖,由於做者認爲這個東西不太好用圖去描述,一想到畫圖,做者就想去畫堆和棧。等畫出來估計幾個小時就過去了。