1. 程式人生 > 其它 >instanceof運算子的實質:Java繼承鏈與JavaScript原型鏈

instanceof運算子的實質:Java繼承鏈與JavaScript原型鏈

instanceof操作符的內部實現機制和隱式原型、顯式原型有直接的關係。instanceof 的作用是判斷一個物件是不是一個函式的例項。instanceof運算子的實質:用來檢測 constructor prototype是否存在於引數 object的原型鏈上。

Javainstanceof

instanceof 嚴格來說是Java中的一個雙目運算子,用來測試一個物件是否為一個類的例項

boolean result = obj instanceof Class

其中 obj 為一個物件,Class 表示一個類或者一個介面當 obj 為 Class 的物件,或者是其直接或間接子類,或者是其介面的實現類,結果result 都返回 true,否則返回false。

總結就是:

  • 只要判斷物件obj 在 屬於Class的繼承鏈上,就返回true

  • obj必須為物件,因此 obj 必須為引用型別,不能是基本型別

    • 基本資料型別:byte short int long float double char boolean

    • 特殊型別:null

      該型別沒有名字,所以不可能宣告為 null 型別的變數或者轉換為 null 型別,null 引用是 null 型別表示式唯一可能的值,null 引用也可以轉換為任意引用型別

  • 如果 obj 為 null,那麼將返回 false。

編譯器會檢查 obj 是否能轉換成右邊的class型別,如果不能轉換則直接報錯,如果不能確定型別,則通過編譯,具體看執行時定

java資料型別看參看《再談Java資料結構—分析底層實現與應用注意事項

JavaScript資料結構參看《再談js物件資料結構底層實現原理-object array map set

對於前端,這裡只是一個引子

JavaScriptinstanceof

The instanceof operator tests whether the prototype property of a constructor appears anywhere in the prototype chain of an object.

instanceof 運算子用來檢測 constructor.prototype 是否存在於引數 object 的原型鏈上。

instanceof操作符的內部實現機制和隱式原型、顯式原型有直接的關係。instanceof的左值一般是一個物件,右值一般是一個建構函式,用來判斷左值是否是右值的例項。它的實現原理是沿著左值的__proto__一直尋找到原型鏈的末端,直到其等於右值的prototype為止。

instanceof 的作用是判斷一個物件是不是一個函式的例項。比如 obj instanceof fn, 實際上是判斷fn的prototype是不是在obj的原型鏈上。所以

instanceof運算子的實質:用來檢測 constructor.prototype是否存在於引數 object的原型鏈上。

原生JS實現instanceof功能

核心就是左邊物件的__proto__的指向是否等於右邊的prototype屬性

functioninstanceofMethod(left,right){
letprototype=right.prototype;
letproto=left.__proto__;
while(true){
if(proto===prototype)returntrue;
if(proto===null)returnfalse;
//若本次查詢無結果,則沿著原型鏈向上查詢
proto=proto.__proto__;
}
}

在《再談javascriptjs原型與原型鏈及繼承相關問題

根據上圖展示的Object和Function的繼承依賴關係,我們可以通過instanceof操作符來看一下Object和Function的關係:

console.log(ObjectinstanceofObject);//true
console.log(ObjectinstanceofFunction);//true
console.log(FunctioninstanceofObject);//true
console.log(FunctioninstanceofFunction);//true

函式與物件相互依存,分別定義了事物的描述方法和事物的生成方法,在生成JS萬物的過程中缺一不可。

FunctioninstanceofFunction//true,why?Function.prototype是原型物件,卻是函式物件
  • Object特殊在Object.prototype是憑空出來的。語法上,所有的{}都會被解釋為new Object();

  • Function特殊在__proto__ == prototype。語法上,所有的函式宣告都會被解釋為new Function()。

我們來看Function和Object的特殊之處:

  1. Object是由Function建立的:因為Object.__proto__ === Funciton.prototype;

  2. 同理,Function.prototype是由Object.prototype建立的;

  3. Funciton是由Function自己建立的!

  4. Object.prototype是憑空出來的!

null instanceof null

基本包裝型別物件:ECMAScript還提供了3個特殊的引用型別: Boolean、Number、String。這些型別與其他內建物件型別相似,但同時具有各自的基本型別相應的特殊行為。實際上,每當讀取一個基本型別值得時候,後臺就會建立一個對應的基本包裝型別的物件,從而讓我們能夠呼叫一些方法來操作這些資料。包裝型別,是一個專門封裝原始型別的值,並提供對原始型別的值執行操作的API物件

其他內建物件與基本包裝型別物件的區別?

普通的內建物件與基本包裝型別的主要區別就是物件的生命期,使用new操作符建立的引用型別的例項,在執行流離開當前作用域之前都一直儲存在記憶體中,而自動建立的基本包裝型別的物件,則只是存在於一行程式碼的執行瞬間,然後立即被立即銷燬。這意味著我們不能再執行時為基本包裝型別值新增屬性和方法,也沒有所謂的constructor了。

所以

console.log('a'instanceofString)//false
console.log(0instanceofNumber)//false
console.log(falseinstanceofBoolean)//false

null為一切物件的始祖

console.log(null instanceof null)

^

TypeError: Right-hand side of 'instanceof' is not an object

其實對比起來,和java 大同小異

轉載本站文章《instanceof運算子的實質:Java繼承鏈與JavaScript原型鏈》,
請註明出處:https://www.zhoulujun.cn/html/webfront/ECMAScript/js/2015_1231_8493.html