關於__proto__和prototype


首先放一個在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. 基礎是上面提到的那兩個基本規則!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章