首先放一個在stackoverflow上的圖片,該問題的地址:
http://stackoverflow.com/questions/650764/how-does-proto-differ-from-constructor-prototype
記住兩條基本規則:
1. 所有的構造函數(也就是類,雖然JS中沒有類的概念)和函數的__ptoto__都指向Function.prototype,它是一個空函數。
2. 所有對象的__proto__都指向它的構造函數的prototype。
下面以例子來說明規則:
Number.__proto__ === Function.prototype // true
Boolean.__proto__ === Function.prototype // true
String.__proto__ === Function.prototype // true
Object.__proto__ === Function.prototype // true
Function.__proto__ === Function.prototype // true
Array.__proto__ === Function.prototype // true
RegExp.__proto__ === Function.prototype // true
Error.__proto__ === Function.prototype // true
Date.__proto__ === Function.prototype // true
上面都是JS內置的構造函數。另外對於普通的函數:
function f(){};
f.__proto__ === Function.prototype // true
其實在JS中構造函數和一般函數沒有本質的區別,只不過構造函數一般是通過new新的對象來使用,作爲類存在,而普通函數都是直接調用。
Math.__proto__ === Object.prototype // true
JSON.__proto__ === Object.prototype // true
Math和JSON是JS內置的對象,使用時無需通過new新的對象來使用,所以它們的構造函數也就是Object。
"abc".__proto__ === String.prototype // true
String對象的構造函數是String
var x = {a: 123};
x.__proto__ == Object.prototype // true
一般的對象的構造函數同樣是Object。
function Person(){};
Person.prototype.x = 123;
var p = new Person();
p.__proto__ === Person.prototype // true
對於自定義的構造函數也是一樣的,而且:
p.__proto__ === p.constructor.prototype // true
因爲p.constructor就是Person。(條件是修改原型)
但是如果是重寫原型:
function Person(name) {
this.name = name
}
// 重寫原型
Person.prototype = {
getName: function() {}
}
var p = new Person('jack')
console.log(p.__proto__ === Person.prototype) // true
console.log(p.__proto__ === p.constructor.prototype) // false
那麼p.constructor就是Object了,因爲p本身沒有constructor那麼就去尋找p.__proto__的constructor,即Person.prototype的constructor,由於上面Person.prototype是重寫的新的對象,它的constructor是Object。
Function.prototype是唯一一個typeof XXX.prototype爲 “function”的prototype。其它的構造器的prototype都是一個對象。
總結:
1. __proto__在編程中儘量避免使用,研究它只是用於理解原型和原型鏈的關係。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto
2. 在查找對象的屬性時,首先查找自身屬性,如果沒有,查找對象的__proto__中的屬性,以此類推。
3. prototype可以理解爲爲子對象共享屬性的一個接口。
4. __proto__中的屬性可以直接 對象名. 取得,而prototype中的屬性必須 對象名.prototype.name 取得。
5. 基礎是上面提到的那兩個基本規則!