instanceof運算子的實質:Java繼承鏈與JavaScript原型鏈
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的特殊之處:
-
Object是由Function建立的:因為Object.__proto__ === Funciton.prototype;
-
同理,Function.prototype是由Object.prototype建立的;
-
Funciton是由Function自己建立的!
-
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