原型和原型鏈

lvkehao發表於2024-04-13

原型

概念

  • 無論什麼時候,只要建立了一個函式,那麼就會為之建立一個prototype屬性,這個屬性指向了函式的原型物件
  • 在預設情況下,每個原型物件同樣會建立一個constructor屬性,用於指向prototype屬性所在函式的指標。
  • 使用建構函式建立的物件,會建立一個名為[[prototype]]的指標指向建構函式的原型物件

三個屬性

  • prototype:每一個函式都有一個prototype屬性,指向原型物件。
    • 例外:Function.prototype.bind()沒有prototype屬性
  • [[prototype]:每一個例項物件都有一個[[prototype]]內部屬性,指向建構函式的原型物件。
  • constructor:每一個原型物件都有一個constructor屬性,指向關聯的建構函式。

舉個?

  • 建立了一個函式後,預設情況下,其原型物件只獲得一個constructor屬性,該屬性指向Person函式。
// 建構函式
function Person() {}
console.log(Person.prototype);
複製程式碼

原型和原型鏈

  • 可以給原型物件新增屬性和方法
// 建構函式
function Person() {}
Person.prototype.country = 'China';
Person.prototype.sex = 'man';
Person.prototype.age = 26;
Person.prototype.sayAge = function() {
	console.log(this.age);
}
console.log(Person.prototype);
複製程式碼

原型和原型鏈

  • 每個物件例項都有一個__proto__屬性去訪問原型物件,這裡的__proto__屬性是瀏覽器提供用於訪問例項物件內部屬性[[prototype]]。ECMAScript5中增加了一個Object.getPrototypeOf()方法,用於物件訪問其原型物件。
// 建構函式
function Person() {}
Person.prototype.country = 'China';
Person.prototype.sex = 'man';
Person.prototype.age = 26;
Person.prototype.getAge = function() {
	console.log(this.age);
}

var person1 = new Person();
person1.getAge();
console.log(person1);

var person2 = new Person();
person2.getAge();
console.log(person2);
複製程式碼

原型和原型鏈

  • 它們之間的關係如下圖:
    原型和原型鏈
  • 由於原型物件會共享自身的屬性和方法,因此這裡建立的2個Person物件例項能夠直接訪問getAge()
    • 當呼叫person1.getAge()時,會先在person1例項中搜尋getAge(),若找到就返回;若沒有找到,則到person1的原型物件中去搜尋。這裡進行了2次搜尋工作。
    • 若在例項物件中新增了原型物件中同名的屬性,那麼該屬性並不會重寫原型物件中的值,只是作為例項物件自己的屬性,不會被共享。例如:
// 建構函式
function Person() {}
Person.prototype.country = 'China';
Person.prototype.sex = 'man';
Person.prototype.age = 26;
Person.prototype.getAge = function() {
	console.log(this.age);
}

var person1 = new Person();
person1.age = 28;
console.log(person1);
複製程式碼

原型和原型鏈

  • 可以看出:只是為person1物件新增了一個age屬性,而原型物件中的age屬性的值不改變。
  • console.log(person1.age)會輸出28,而不是26。此時訪問的是person1物件中的age屬性。可以使用delete person1.age刪除本物件上的屬性,刪除之後訪問的就是原型物件上面的age屬性了。
  • 可以使用hasOwnProperty()來檢測一個屬性是存在於物件例項中,還是原型物件中。

原型鏈

概念

  • 當一個例項物件的原型物件是另一種型別的例項物件,且這個例項物件的原型物件同樣又是另一種型別的例項物件,以此下去,最終會就形成了一個有限的原型鏈。
  • 原型鏈是JavaScript中一種能夠實現繼承的方式。

舉個?

function Animal() {}
Animal.prototype.category = 'Animal';

function Cat() {}
// Cat的原型物件賦值為Animal例項物件
Cat.prototype = new Animal();
Cat.prototype.category = 'Cat';

function Tiger() {}
// Tiger的原型物件賦值為Cat例項物件
Tiger.prototype = new Cat();
Tiger.prototype.category = 'Tiger';

var tiger = new Tiger();
console.log(tiger);
複製程式碼

原型和原型鏈

  • tiger指向Tiger的原型,Tiger的原型指向Cat的原型,Cat的原型指向Animal的原型,Animal的原型指向Object的原型。
  • 簡單來說:__proto__屬性連線每個物件,形成了原型鏈。任何原型鏈的最底層都是Object.prototype
  • 注意:Tiger例項物件和Cat例項物件的原型物件都沒有constructor屬性,這是因為我們重寫了原型物件,將其賦值為了使用new建立的新物件。

相關文章