雖然在JavaScript里一切皆對象,但為了理解原型鏈系統,我們需要將JavaScript的對象分為對象和函數兩大類。在此基礎上,JavaScript的原型鏈邏輯遵從以下通用規則:
- 對象有__proto__屬性,函數有prototype屬性;
- 對象由函數生成;
- 生成對象時,對象的__proto__屬性指向函數的prototype屬性。
在沒有手動修改__proto__屬性的指向時,以上三條便是JavaScript默認原型鏈指向邏輯。
1、一般情況:
// 創建空對象時,實際上我們是用Object函數來生成對象的:
var o = {}
o.__proto__ === Object.prototype
// ==> true
// 我們也可以顯式的使用Object函數來創建對象:
var o = Object()
o.__proto__ === Object.prototype
// ==> true
// 當我們使用函數來創建自定義的對象時,上面的規則同樣適用:
function MyObj(){}
typeof MyObj
// ==> "function"
var mo = new MyObj()
mo.__proto__ === MyObj.prototype
// ==> true
2、函數對象
既然JavaScript里“一切皆對象”,那函數自然也是對象的一種。對於函數作為對象來說,上面的規則同樣適用:
// 函數對象都是由Function函數生成的:
>function fn(){}
>fn.__proto__ === Function.prototype
// ==> true
// Function函數本身作為對象時,生成它的函數是他自身!
>Function.__proto__ === Function.prototype
// ==> true
// Object函數既然是函數,那生成它的函數自然是Function函數咯:
>Object.__proto__ === Function.prototype
// ==> true
來看一個例子:
function Say(name, age) {
this.name = name;
this.age = age;
}
var person = new Say('jone', 30);
console.log(person instanceof Say); // ==> true
console.log(person.__proto__ === Say.prototype); // ==> true
console.log(person.__proto__.constructor === Say.prototype.constructor); // ==> true
var obj = {};
console.log(obj.__proto__ == Object.prototype) // ==> true
var fn = function() {};
console.log(fn.__proto__ === Function.prototype); // ==> true
總結:
js里所有的對象都有__proto__屬性(對象,函數),指向構造該對象的構造函數的原型。
只有函數function才具有prototype屬性。這個屬性是一個指針,指向一個對象,這個對象的用途就是包含所有實例共享的屬性和方法(我們把這個對象叫做原型對象)。原型對象也有一個屬性,叫做constructor,這個屬性包含了一個指針,指回原構造函數。