1. 程式人生 > >談談JavaScript的原型、原型鏈、建構函式、prototype、__proto__和constructor

談談JavaScript的原型、原型鏈、建構函式、prototype、__proto__和constructor

  原型、原型鏈、建構函式是JavaScript比較難的知識點,但是它們又功能強大,是我們進行元件開發、模組開發必須掌握的技能,翻閱網上相關的博文,個人覺得這幾篇博文不錯,可以一讀:
  1)湯姆大叔:強大的原型和原型鏈
  2)深入理解JavaScript系列(10):JavaScript核心(晉級高手必讀篇)
  3)三張圖搞懂JavaScript的原型物件與原型鏈
  4)Js中Prototype、__ proto __、Constructor、Object、Function關係介紹
  5)前端基礎進階(九):詳解面向物件、建構函式、原型與原型鏈
  因此,本文不再大篇幅圖文介紹JavaScript物件、原型、原型鏈、建構函式等知識點,而是力求用簡單文字、程式碼輸出剖析prototype、__proto__和constructor三者間的關係。

1、prototype和__proto__

  • 1)prototype是函式(function)才有的屬性;
  • 2)__proto__是每個物件(object)都有的屬性,指向物件建構函式的prototype;
var a = {};				// 等同 a = new Object();
console.log(a.prototype);  //普通物件沒有prototype屬性,->undefined
console.log(a.__proto__);  //建構函式原型, Object.prototype, ->Object{...}

var b = function
(){} console.log(b.prototype); //b {} console.log(b.__proto__); // = Function.prototype, ->function() {}

說明:Function.prototype = function,是特例,下文會繼續講解。

  • 3)__proto__構成原型鏈,Object.prototype.__proto __= null,原型鏈結束
var a = {};
console.log(a.__proto__);  //=Object.prototype, ->Object {}
console.
log(a.__proto__.__proto__); //=Object.prototype.__proto__, ->null

原型鏈從繼承角度理解就是找父類,以Java為例:
1)a是一個普通物件例項,則a的父類是基類Object;
2)基類Object沒有父類,因此可以理解其父類為null。
而JavaScript用原型連結串列示這種繼承關係,用物件的__proto__屬性構成原型鏈:
1)a.__ proto __ = Object.prototype
2)a.__ proto __ . __ proto __ = Object.prototype. __ proto __ = null

  • 4)__ proto __,通常指向物件建構函式的prototype,有一種情況例外Object.create方式建立的物件。
var a1 = {};
var a2 = Object.create(a1);
console.log(a2.__proto__==a1)	->true

用Object.create(a1)建立的物件,其__proto__會指向a1,因此對於a2來說,其原型鏈為:
a2.__ proto __ = a1;
a1.__ proto __ = Object.prototype;
a2.__ proto __ . __ proto __ . __ proto __ = null

2、Prototype和Constructor

在 JavaScript 中,每個函式物件都有prototype屬性,用於引用原型物件。prototype物件又有隱藏屬性constructor,它反過來引用函式本身,是一種迴圈引用。

function Animal(){
}
var anim = new Animal();
console.log(anim.constructor===Animal);	//anim由Animal構造出來,->true
console.log(Animal===Animal.prototype.constructor); //prototype物件的隱藏屬性constructor反過來引用函式本身,->true
/**
 * Animal = new Function()
 * 因此Animal.constructor = Function,
 * 而 Function = Function.prototype.constructor
 * Animal.constructor = Function.prototype.constructor
 */
console.log(Animal.constructor===Function.prototype.constructor); // ->true
console.log(Function.prototype.constructor===Function);    //true

3、深入理解Function、Object

JavaScript中有幾個迷惑的地方
1)Function、Object是函式;
2)new Function仍然是函式,new Object卻是物件;
3)new (new Function) 又是物件;

var o2 =new Object();
var f3 = new Function('str','console.log(str)');
console.log('typeof Object:'+typeof Object);        //function
console.log('typeof Function:'+typeof Function);    //function
console.log('typeof o2:'+typeof o2);   				//object
console.log('typeof f3:'+typeof f3);   				//function
console.log('typeof new f3:'+typeof new f3());   	//object

Function.prototype = function,是一個特例

console.log(typeof Function.prototype);  //這是一個特例, ->function
console.log(typeof Function.__proto__);  //function
console.log(typeof Function.__proto__ == Function.prototype) ->true
console.log(typeof Function.prototype.prototype); //undefined, 正常來說Function.prototype = function, function.prototype = object
console.log(typeof Function.prototype.__proto__); //object,這個要記住,後面會詳細解釋

console.log(typeof Object.prototype);	//object, 好理解,Object是一個function
console.log(typeof Object.__proto__); //function, 好理解, Object = new Function,Object.__proto__ = Function.prototype
console.log(Object.prototype.prototype); //undefied, 好理解, Object.prototype = object(只有function才有prototype,所以prototype=undefiend)
console.log(Object.prototype.__proto__===null);  //null, 必須記住,原型鏈結束

console.log(Function.prototype===Object.__proto__);   //true,上面程式碼已經解釋
console.log(Function.__proto__===Object.__proto__);   //true, 因為Function.prototype = Function.__proto__
console.log(Function.prototype.__proto__===Object.prototype);   //true,有點不明白?

Function.prototype. __ proto __=Object.prototype解釋

console.log(Function instanceof  Object); // true
console.log(Object instanceof Function);  // true

根據instanceof原理,我們可以得出結論:

  • Object.prototype(object)在Function的原型鏈上有;
    Function . __ proto __ = function, != Object.prototype
    因此只有Function . __ proto__ . __ proto __ = Object.prototype,
    由於Function . __ proto__ = Function.prototype, 因此:
    Function.prototype. __ proto __=Object.prototype
  • Function.prototype在Object的原型鏈上有;