原型與原型鏈詳解

前言

與大部分面嚮對象語言不一樣,ES6以前中並無引入類(class)的概念,JavaScript並不是經過類而是直接經過構造函數來建立實例。在介紹原型和原型鏈以前,咱們有必要先複習一下構造函數的知識。git

1、構造函數

構造函數模式的目的就是爲了建立一個自定義類,而且建立這個類的實例。構造函數模式中擁有了類和實例的概念,而且實例和實例之間是相互獨立的,即實例識別。github

構造函數就是一個普通的函數,建立方式和普通函數沒有區別,不一樣的是構造函數習慣上首字母大寫。另外就是調用方式的不一樣,普通函數是直接調用,而構造函數須要使用new關鍵字來調用bash

function Person(name, age, gender) {
		this.name = name
		this.age = age
		this.gender = gender
		this.sayName = function () {
			alert(this.name);
		}
	}
	var per = new Person("孫悟空", 18, "男");
	function Dog(name, age, gender) {
		this.name = name
		this.age = age
		this.gender = gender
	}
	var dog = new Dog("旺財", 4, "雄")
	console.log(per);//當咱們直接在頁面中打印一個對象時,事件上是輸出的對象的toString()方法的返回值
	console.log(dog);
複製代碼

每建立一個Person構造函數,在Person構造函數中,爲每個對象都添加了一個sayName方法,也就是說構造函數每執行一次就會建立一個新的sayName方法。這樣就致使了構造函數執行一次就會建立一個新的方法,執行10000次就會建立10000個新的方法,而10000個方法都是一摸同樣的,爲何不把這個方法單獨放到一個地方,並讓全部的實例均可以訪問到呢?這就須要原型(prototype)函數

2、原型

在JavaScript中,每當定義一個函數數據類型(普通函數、類)時候,都會天生自帶一個prototype屬性,這個屬性指向函數的原型對象,而且這個屬性是一個對象數據類型的值。學習

讓咱們用一張圖表示構造函數和實例原型之間的關係:this

原型對象就至關於一個公共的區域,全部同一個類的實例均可以訪問到這個原型對象,咱們能夠將對象中共有的內容,統一設置到原型對象中。

3、原型鏈

1.__proto__constructor

每個對象數據類型(普通的對象、實例、prototype......)也天生自帶一個屬性__proto__,屬性值是當前實例所屬類的原型(prototype)。原型對象中有一個屬性constructor, 它指向函數對象。spa

function Person() {}
    var person = new Person()
    console.log(person.__proto__ === Person.prototype)//true
    console.log(Person.prototype.constructor===Person)//true
    //順便學習一個ES5的方法,能夠得到對象的原型
    console.log(Object.getPrototypeOf(person) === Person.prototype) // true
複製代碼

2.何爲原型鏈

在JavaScript中萬物都是對象,對象和對象之間也有關係,並非孤立存在的。對象之間的繼承關係,在JavaScript中是經過prototype對象指向父類對象,直到指向Object對象爲止,這樣就造成了一個原型指向的鏈條,專業術語稱之爲原型鏈prototype

舉例說明:person → Person → Object ,普通人繼承人類,人類繼承對象類code

當咱們訪問對象的一個屬性或方法時,它會先在對象自身中尋找,若是有則直接使用,若是沒有則會去原型對象中尋找,若是找到則直接使用。若是沒有則去原型的原型中尋找,直到找到Object對象的原型,Object對象的原型沒有原型,若是在Object原型中依然沒有找到,則返回undefined。cdn

咱們可使用對象的hasOwnProperty()來檢查對象自身中是否含有該屬性;使用in檢查對象中是否含有某個屬性時,若是對象中沒有可是原型中有,也會返回true

function Person() {}
	Person.prototype.a = 123;
	Person.prototype.sayHello = function () {
	  alert("hello");
	};
	var person = new Person()
	console.log(person.a)//123
	console.log(person.hasOwnProperty('a'));//false
	console.log('a'in person)//true
複製代碼

person實例中沒有a這個屬性,從 person 對象中找不到 a 屬性就會從 person 的原型也就是 person.__proto__ ,也就是 Person.prototype中查找,很幸運地獲得a的值爲123。那假如 person.__proto__中也沒有該屬性,又該如何查找?

當讀取實例的屬性時,若是找不到,就會查找與對象關聯的原型中的屬性,若是還查不到,就去找原型的原型,一直找到最頂層Object爲止。Object是JS中全部對象數據類型的基類(最頂層的類)在Object.prototype上沒有__proto__這個屬性。

console.log(Object.prototype.__proto__ === null) // true
複製代碼

若是以爲文章對你有些許幫助,歡迎在個人GitHub博客點贊和關注,感激涕零!

參考文章

最詳盡的 JS 原型與原型鏈終極詳解,沒有「多是」。(一)

JavaScript深刻之從原型到原型鏈

相關文章
相關標籤/搜索