# proto
ES中的對象都保留著原型的引用。
當對象訪問一個自身沒有的屬性時,會試圖從原型中訪問該屬性。
而原型也是一個對象。如果在原型中仍然沒找到該屬性,將試圖從原型的原型中訪問……

因為其鏈表的結構,所以被稱為原型鏈。
chrome瀏覽器環境中的原型是在對象屬性上顯式的實現,以下的例子有通過對__proto__屬性訪問改變對象的原型。
但這在真正的編程環境中是不被推薦的,因為不是所有的瀏覽器都有__proto__的實現。
~~~
var foo = {};
var prototype = {
name: 'I in prototype.'
};
foo.__proto__ = prototype;
console.dir(foo.name);//I in prototype.
~~~
# Function
對一個Function類對象使用**new**關鍵字,可以構造一個指定原型的對象。
而這種方式所指定的原型,是該Function類對象的**prototype**。
~~~
var classA = function () { };
classA.prototype = { name: 'I in prototype.' };
var foo = new classA();
console.dir(foo.name);//I in prototype.
~~~
這種使用一個函數對象A構造出另一個對象B的行為,被稱為類的實例化。
A為B的類,B為A的實例。
使用**instanceof**關鍵字可以判斷一個對象是否為一個函數對象的實例。
~~~
foo instanceof classA;//true
~~~
實際上instanceof判斷的是,一個對象的原型鏈中的其中一個原型是否為另一個函數對象的prototype。
~~~
var mock = function () { };
mock.prototype = classA.prototype;
foo instanceof mock;//true
~~~
PS:該實例確實能通過原型鏈使用該類提供的屬性,所以instanceof的語義并沒有發生變化,A instanceof B仍然是判斷A是否為B的實例。
值得一提的是Function對象由其本身構造。
~~~
Function.__proto__ === Function.prototype;//true;不恰當的例子。
~~~
而Function對象的prototype則是由Object對象構造。
~~~
Function.prototype.__proto__ === Object.prototype;//true;不恰當的例子
~~~
# Object
因為對象都有其原型,而原型無論來自哪個函數對象,也改變不了其是對象的事實,最終都會指向能構造一般對象的Object的prototype。
所以才有那么一句話,ES所有對象都派生于Object。
~~~
Function instanceof Object;//true
Number instanceof Object;//true
new Number() instanceof Object;//true
//..
~~~
那么Object.prototype的原型是什么?原型鏈到此就結束了。在實現上,Object.prototype的原型是null值,用來作為原型鏈的結束符號。
~~~
Object.prototype.__proto__ === null;//true;不恰當的例子
~~~
# 構造函數
用來構造對象的函數對象,他的函數本身被稱為構造函數。
構造函數可以接受參數,在執行時能通過this關鍵字對構造出來的對象進行操作。
~~~
var classA = function (name) {
this.name = name;
};
var foo = new classA('foo');
console.dir(foo);
~~~

new classA的執行步驟可以看做是:
1. 新構造一個對象。
2. 將對象的原型指向classA的prototype。
3. 使對象調用classA這個構造函數。
4. 返回該對象。
以下用代碼模仿這個過程。
~~~
var classA = {
construct: function () { },
prototype: {},
new: function () {
var obj = {};//1. 新構造一個對象。
obj.__proto__ = this.prototype;//2. 將對象的原型指向classA的prototype。
this.construct.apply(obj, arguments);//3. 使對象調用classA這個構造函數。
return obj;//4. 返回該對象。
}
};
var foo = classA.new()
foo.__proto__ === classA.prototype;//true
~~~
同時,用代碼模仿原型鏈的訪問。
~~~
var __index = function (obj, key) {
//嘗試訪問鍵為key的屬性。
if (obj[key]) {
return obj[key];
}
else {
//存在原型,嘗試從原型中訪問。
if (obj.__proto__) {
return __index(obj.__proto__, key);
}
else {
return undefined;
}
}
};
~~~