【5】JavaScript 函式高階——原型與原型鏈深入理解(圖解)
原型與原型鏈深入理解(圖解)
原型( prototype
)
函式的 prototype
屬性(圖)
- 每個函式都有一個
prototype
屬性,它預設指向一個Object
空物件(即稱為:原型物件) - 原型物件中有一個屬性
constructor
,它指向函式物件
給原型物件新增屬性(一般都是新增方法)
- 作用:函式的所有例項物件自動擁有圓形中的屬性(方法)
顯式原型與隱式原型
- 每個函式
function
都有一個prototype
屬性,即 顯式原型 - 每個例項物件都有一個
__proto__
,可稱為隱式原型 - 例項物件的隱式原型的值
===
其對應建構函式的顯示原型的值 - 記憶體結構(圖)
-
總結:
- 函式的
prototype
屬性:在定義函式時自動新增的,預設值是一個空的Object
物件 - 物件的
__proto__
屬性:建立物件時自動新增的,預設值為建構函式的prototype
屬性值 - 程式設計師能直接操作顯示原型,但不能直接操作隱式原型(
ES6
之前)
- 函式的
原型鏈
原型鏈(圖解)
-
訪問一個物件的屬性時,
__proto__ undefined
- 原型鏈的別名:隱式原型連
- 原型鏈的作用:查詢物件的屬性(方法)
建構函式/原型/例項物件的關係(圖解)
var o1 = new Object()
var o2 = {}
建構函式/原型/例項物件的關係2(圖解)
下面這個圖需要仔細理解。
原型繼承
- 建構函式的例項物件自動擁有建構函式原型物件的屬性(方法)
- 利用的就是原型鏈
原型鏈——屬性問題
- 讀取物件的屬性值時:會自動到原型鏈中查詢
- 設定物件的屬性值時:不會查詢原型鏈,如果當前物件中沒有此屬性,直接新增此屬性並設定其值
- 方法一般定義在原型中,屬性一般通過建構函式定義在物件本身上。
探索 instanceof
instanceof
是如何判斷的?
- 表示式:
A instanceof B
- 如果
B
函式的顯式原型物件在A
物件的(隱式)原型鏈上,返回true
,否則返回false
Function
是通過 new
自己產生的例項
案例1
function Foo() {} var f1 = new Foo(); console.log(f1 instanceof Foo); // true console.log(f1 instanceof Object); // true
案例2(重要)
console.log(Object instanceof Function); // true console.log(Object instanceof Object); // true console.log(Function instanceof Function); // true console.log(Function instanceof Object); // true function Foo() {} console.log(Object instanceofFoo); // false
注意: Function
的顯示原型和隱式原型是一樣的。
面試題
測試題1
var A = function() { } A.prototype.n = 1 var b = new A() A.prototype = { n: 2, m: 3 } var c = new A() console.log(b.n, b.m, c.n, c.m) // 1 undefined 2 3
測試題2
var F = function(){}; Object.prototype.a = function(){ console.log('a()') }; Function.prototype.b = function(){ console.log('b()') }; var f = new F(); f.a() // a() f.b() // 報錯f.b is not a function F.a() // a() F.b() // b()
對照下圖理解: