最近在看到了JavaScript的原型鏈這里,一直認為是比較復雜的就去多了解了下,本來是准備寫點什么的,發現腦子里亂亂的無從下手,然后又去翻查了各種資料才有點眉目,就此算是做個總結一下吧。
原型
JavaScript 常被描述為一種基於原型的語言 (prototype-based language)——每個對象擁有一個原型對象。對象以原型為模板繼承原型的方法和屬性,以此類推就成了“原型鏈”。具體的說:"它將通過new關鍵字創建的<對象實例>鏈接會創建它們的<構造函數>" 。就這樣,我們可以共享或繼承通用的方法和屬性。為什么有原型和原型鏈,這就和js的繼承機制設計思想有關了,如果有興趣可以去看阮一峰的這篇博客了解下。
首先我把需要注意的幾點放上面,思維圖放文章后面。
1 .每個對象都具有一個__ proto __ 屬性,並且指向自身的構造函數的prototype。
2 .創建一個函數 數組,都會有一個prototype(原型對象,不管是否當做構造函數)
3 .每個構造函數都具有名為prototype的方法(構造函數標准為首字母大寫,例如Function()Object()等以及自己創建的)
4 .調用構造函數的模式:
var 對象實例 = new 構造函數()
原型鏈概要
JavaScript中創建的每個對象設置一個原型指向它的原型對象,例如當我們訪問obj.xxx時,JavaScript引擎就會在當前對象上尋找,如果沒有就回去他的原型對象上尋找,如果還沒有就會去下一個原型對象,直到Object.prototype還沒有就會指向null,並且返回一個undefined。所以js為了給你個undefined可謂經歷了一波三折啊
var obj = [1, 2, 3]; console.log(obj.xxx) //undefined
1.在obj對象中查找該屬性; 如果沒有找到就去下一家 2.則在Array.prototype中查找該屬性; 但它在那里也沒有定義 3.最后查找的地方就是Object.prototype還沒有? 繼續向下走只有最終指向的null了 沒辦法,只能返回給你undefined~~~
其原型鏈是:
obj ----> Array.prototype ----> Object.prototype ----> null
當我們創建函數是也同樣如此(函數也是對象)
function fun(){ console.log(function) } fun.__proto__ === Function.prototype Function.prototype.__proto__ === Object.prototype Object.prototype.__proto__ ===null
其原型鏈是:
fun----> function .prototype ----> Object.prototype ----> null
構造函數
除了使用數組和函數,以及全局對象(臨時轉換),我們還可以通過構造函數的方式先創建對象,來定義一個構造函數。
調用構造函數的模式:var 對象實例 = new 構造函數()
(調用構造函數千萬不能忘記寫new。為了區分普通函數和構造函數,按照約定,構造函數首字母應當大寫,而普通函數首字母應當小寫)
function Student(){ this.name=Leonardo } //我們構造一個函數Student,這個數有Function生成
var stu = new Student() //我們創建一個函數stu,設個函數有Student生成(構造函數)
stu.__proto__ === Student.prototype //stu的__proto__ 指向它的構造函數
Student.prototype.__proto__ === Object.prototype //Student.prototype的__proto__ 指向它的構造函數
Object.prototype.__proto__ ===null
//Object.prototype.的__proto__ 指向null
constructor(構造函數屬性)
我們除了使用. __ proto __ 鏈接,還可以使用構造函數屬性:
事實上,.__ proto __ === constructor.prototype
function fun(){ console.log(function) } fun.constructor.prototype=== Function.prototype Function.prototype.constructor.prototype=== Object.prototype Object.prototype.constructor.prototype===null
prototype屬性
prototype 屬性是繼承成員被定義的地方,繼承的屬性和方法是定義在 prototype 屬性之上的。
對象的__ proto __ 屬性通常與其構造函數的prototype屬性相互對應;
所有構造函數的的prototype方法的__ proto __ 都指向Object.prototype(除了....Object.prototype自身)
替換prototype屬性的默認值
我們可以用一個新值來替換prototype屬性的默認值,但是需要特別注意的是:這么做會刪除在"預制"原型對象中找到的默認的constructor屬性。繼承原型屬性的實例總是能夠獲得最新值
用新對象替換prototype屬性不會更新以前的實例
創建一個實例時,該實例將在實例化時綁定至"剛完成"的原型,提供一個新對象作為prototype屬性不會更新已創建的實例和原型之間的連接,所以一旦開始創建實例,就不應用一個新對象那個來替換對象的原型,這樣將會導致實例有一個指向不同原型的鏈接
自定義構造函數實現原型繼承
當我們在自定義構造函數時,同樣可以實現原型繼承。
原型鏈概念圖,可以結合理解:
