JavaScript原型與原型鏈知識點詳解

2022-07-06 14:00:38
本篇文章給大家帶來了關於的相關知識,其中主要整理了原型與原型鏈的相關問題,包括了原型的概念、函數原型上的constructor屬性、原型鏈的理解等等內容,下面一起來看一下,希望對大家有幫助。

【相關推薦:、】

一、原型

1.概念

在JavaScript中,函數是一個包含屬性和方法的Function型別的物件。而原型(Prototype)就是Function型別物件的一個屬性。

在函數定義時就包含了prototype屬性,它的初始值是一個空物件。在JavaScript中並沒有定義函數的原型型別,所以原型可以是任何型別。

原型是用於儲存物件的共用屬性和方法的,原型的屬性和方法並不會影響函數本身的屬性和方法。

// Function型別的屬性->所有函數都具有的屬性
console.log(Function.prototype);//[Function]

// 定義函數
function fn() {
    console.log('this is function');
}

//原型的預設值是空物件
console.log(fn.prototype);//fn {}

// 函數包含建構函式 ——> 所有參照型別其實都是建構函式
console.log(Number.prototype); //[Number: 0]

console.log(Object.prototype);//{}

2.獲取原型

通過如下兩種方式可以獲取物件的原型,從而設定共用的屬性和方法:

  • 通過建構函式的prototype屬性
  • 通過Object物件的getPrototype(obj)方法。
function fn() {
    console.log('this is function');
}

//使用存取物件的屬性語法結構
console.log(fn.prototype);//fn {}
console.log(fn['prototype']);//fn {}

//Object型別提供getPrototypeOf()方法
console.log(Object.getPrototypeOf(fn));//[Function]

3.瞭解函數原型上的constructor屬性

Object.getOwnPropertyDescriptors() 方法用來獲取一個物件的所有自身屬性的描述符。

var result = Object.getOwnPropertyDescriptor(Object.prototype,'constructor');
console.log(result) //輸出結果如下:
//{
//   value: [Function: Object],
//   writable: true,
//   enumerable: false,
//   configurable: true
// }

constructor是在建立函數的時候自動新增的,指向建構函式本身

4.設定原型上的屬性和方法

通過如下兩種方式可以設定原型的屬性和方法:

  • 原型的屬性和方法單獨進行定義。
建構函式.prototype.屬性名 = 屬性值 ;建構函式.prototype.方法名 = function(){} ;
  • 直接為原型定義一個新物件。

當我們需要在原型上新增很多很多屬性的時候 一遍一遍的去寫 建構函式.prototype.屬性名 太麻煩了,可以直接修改整個prototype

建構函式.prototype = {
    屬性名:屬性值,
    方法名:function(){}}
function foo () {}foo.prototype = {
    constructor: foo,
    name: 'jam',
    age: 18,
    address: '北京市'}var fn = new foo()console.log(fn.address) // 北京市

5.isPrototypeOf()方法

每個物件中都會具有一個isPrototypeOf()方法,該方法用來判斷一個物件是否是另一個物件的原型。

範例程式碼如下:
// 通過初始化器方式定義物件
var obj = {
    name:'jam'
}
// 定義建構函式
function Hero() {}
// 將物件obj賦值給建構函式Hero的原型
Hero.prototype = obj;
// 通過建構函式建立物件
var hero = new Hero();

// isPrototypeOf()方法判斷指定物件是否是另一個物件的原型
var result = obj.isPrototypeOf(hero);
console.log(result);//true

驗證了obj物件是hero物件的原型

二、原型鏈

1.原型鏈的理解

接下來我們使用一段程式碼來展開對原型鏈的認識:

場景:查詢obj物件身上的address屬性
js執行的步驟:
    1. 會觸發get操作
    2. 在當前的物件中查詢屬性
    3. 如果沒有找到,這個時候會去原型鏈(__proto__)物件上查詢
       1. 查詢到結束
       2. 沒查詢到一直順著原型鏈查詢,直到查詢到頂層原型(頂層原型是什麼暫時賣個關子)

1.1 範例程式碼如下:

var obj = {
    name: 'jam',
    age: 19
}
/* 
    要求:查詢obj物件身上的address屬性
*/

// 原型鏈一層一層向上查詢,如果一直沒有找到,直到查詢到頂層原型結束
obj.__proto__ = {}
obj.__proto__.__proto__ = {}
obj.__proto__.__proto__.__proto__ = {
    address: '北京市'
}

console.log(obj.address) // 北京市
console.log(obj.__proto__.__proto__.__proto__)  // { address: '北京市' }

1.2 記憶體圖

在這裡插入圖片描述

最終查詢到address屬性
那麼這裡有一個問題,如果一直沒有查到,會無窮盡的去查詢嗎?接下來我們就來了解一下

2.頂層原型是什麼?

上面我們說到,順著原型鏈不會無休止的去查詢,當查到頂層原型的時候,如果還沒查到就會返回undefined

那麼頂層原型是什麼呢?
範例程式碼如下:

var obj = { name: 'jam' }console.log(obj.__proto__)  // {}console.log(obj.__proto__.__proto__)  // null

字面量物件obj的原型是:{}{}就是頂層的原型
當我們繼續向上列印__proto__時,返回一個null值,就證明上一層就已經是頂層原型了

如下圖是針對第一段程式碼中缺少的頂層原型做的補充:
在這裡插入圖片描述

頂層原型就是Object.prototype

3.Object的原型(Object.prototype)

3.1 那麼什麼地方是原型鏈的盡頭呢?比如第三個物件是否也有原型__proto__屬性呢?

var obj = {name:'jam'}obj.__proto__ = {}obj.__proto__.__proto__ = {}obj.__proto__.__proto__.__proto__ = {}console.log(obj.__proto__.__proto__.__proto__.__proto__)  // {}

我們發現上面列印結果為 空物件{}

  • 事實上這個原型就是我們最頂層的原型了
    var obj = {
      name: 'jam',
      age: 19
      }
      console.log(obj.__proto__)  // {}
      console.log(Object.prototype) // {}
      console.log(obj.__proto__ === Object.prototype) // true

    Object是所有類的父類別
    所以obj.__proto__其實就是Object.prototype ,
    console.log(obj.__proto__ === Object.prototype) // true我們可以看出結果Object.prototype就是頂層原型

  • 從Object直接建立出來的物件的原型都是 {}

3.2 那麼我們可能會問:{}原型有什麼特殊的嘛?

  • 特殊點1:該物件有原型屬性,但是它的原型屬性已經指向的是null,也就是已經是頂層原型了;
    console.log(obj.__proto__.__proto__.__proto__.__proto__.__proto__) // null
  • 特殊點2:該物件上有甚很多預設的屬性和方法;
    • 雖然列印Object.prototype的結果為空物件{},但它不是空的,只是裡面的屬性不可列舉而已,例如我們就列印constructor屬性看看
      <!-- 可以看出是有constructor屬性的 ,並不是空的-->console.log(Object.prototype.constructor)  // [Function: Object]  <!-- constructor 指回了Object -->
    • 我們也可以通過Object.getOwnPropertyDescriptors()方法獲取Object.prototype中的所有自身屬性的描述符。
      console.log(Object.getOwnPropertyDescriptors(Object.prototype)) // 如下長截圖所示
      在這裡插入圖片描述

4.原型鏈關係記憶體圖

在這裡插入圖片描述

【相關推薦:、】

以上就是JavaScript原型與原型鏈知識點詳解的詳細內容,更多請關注TW511.COM其它相關文章!