console.log(typeof ""); console.log(typeof 1 ); console.log(typeof NaN ); console.log(typeof true); console.log(typeof undefined); console.log(typeof function(){}); console.log(typeof isNaN); console.log(typeof Symbol()); console.log(typeof 123n); console.log(typeof []); console.log(typeof {}); console.log(typeof null); console.log(typeof new Date()); console.log(typeof new RegExp()); 2、instanceofinstanceof 是用來判斷 A 是否為 B 的實例,表達式為:A instanceof B,如果 A 是 B 的實例,則返回 true,否則返回 false。 需特別注意:instanceof 檢測的是原型
即instanceof 用來比較一個對象是否為某一個構造函數的實例。instanceof可以準確的判斷複雜數據類型,但是不能正確判斷基本數據類型。
console.log(12 instanceof Number); console.log('22' instanceof String); console.log(true instanceof Boolean); console.log(null instanceof Object); console.log(undefined instanceof Object); console.log(function a() {} instanceof Function); console.log([] instanceof Array); console.log({a: 1} instanceof Object); console.log(new Date() instanceof Date);補充:
instanceof 的原理:主要的實現原理就是只要右邊變量的 prototype在左邊變量的原型鏈上即可。
因此,instanceof 在查找的過程中會遍歷左邊變量的原型鏈,直到找到右邊變量的 prototype,如果存在返回true 否則返回falsefunction new_instance_of(leftVaule, rightVaule) { let rightProto = rightVaule.prototype; leftVaule = leftVaule.__proto__; while (true) { if (leftVaule === null) { return false; } if (leftVaule === rightProto) { return true; } leftVaule = leftVaule.__proto__ }}注意:instanceof 運算時會遞歸查找leftVaule的原型鏈,即leftVaule.__proto__.__proto__.__proto__.__proto__... 直到找到了或者找到頂層為止。
一句話理解其運算規則:instanceof 檢測左側的 __proto__ 原型鏈上,是否存在右側的 prototype 原型。
3、constructorJavaScript中,每個對象都有一個constructor屬性,可以得知某個實例對象,到底是哪一個構造函數產生的, constructor屬性表示原型對象與構造函數之間的關聯關係。
當一個函數F被定義時,JS引擎會為F添加prototype原型,然後在prototype上添加一個constructor屬性,並讓其指向F的引用,F利用原型對象的constructor屬性引用了自身,當F作為構造函數創建對象時,原型上的constructor屬性被遺傳到了新創建的對象上,從原型鏈角度講,構造函數F就是新對象的類型。這樣做的意義是,讓對象誕生以後,就具有可追溯的數據類型。
通過typeof運算符來判斷它是原始的值還是對象。如果是對象,就可以使用constructor屬性來判斷其類型。
如判斷數組的函數:
function isArray(data){ return typeof data == "object" && data.constructor == Array; }isArray([])注意:null 和 undefined 是沒有 constructor 存在的,這兩種類型的數據需要通過其他方式來判斷。
console.log('22'.constructor === String) console.log(true.constructor === Boolean) console.log([].constructor === Array) console.log(document.constructor === HTMLDocument) console.log(window.constructor === Window) console.log(new Number(22).constructor === Number) console.log(new Function().constructor === Function) console.log(new Date().constructor === Date) console.log(new RegExp().constructor === RegExp) console.log(new Error().constructor === Error)2、如果修改了原型對象,一般會同時修改constructor屬性,防止引用的時候出錯。所以,修改原型對象時,一般要同時修改constructor屬性的指向。
function Rectangle(width, height){ this.width = width; this.height = height; this.getArea = function(){ return '矩形的面積為' + (width * height); }}
var rect1 = new Rectangle(40, 20);var rect2 = new Rectangle(50, 20);var rect3 = new Rectangle(60, 20);console.log(rect1.getArea());console.log(rect2.getArea());console.log(rect3.getArea());function Rectangle(width, height){ this.width = width; this.height = height;}
Rectangle.prototype = { constructor: Rectangle, getArea: function(){ return '矩形的面積為' + (this.width * this.height); }}
Object.defineProperties(Rectangle.prototype, { constructor: { enumerable: false, configurable: false, writable: false }, getArea: { enumerable: false, configurable: false, writable: false }})
var rect1 = new Rectangle(40, 20);var rect2 = new Rectangle(50, 20);var rect3 = new Rectangle(60, 20);console.log(rect1.getArea());console.log(rect2.getArea());console.log(rect3.getArea());很多情況下,我們可以使用instanceof運算符或對象的constructor屬性來檢測對象是否為數組。
如很多JS框架就是使用這兩種方法來判斷對象是否為數組類型。 但是檢測在跨框架(cross-frame)頁面中的數組時,會失敗。
原因就是在不同框架(iframe)中創建的數組不會相互共享其prototype屬性。例如:
<script> window.onload=function(){ var iframe_arr=new window.frames[0].Array; console.log(iframe_arr instanceof Array); console.log(iframe_arr.constructor == Array); }</script>4、Object.prototype.toString.call()獲取對象o的class屬性。這是一個內部屬性,
連接字符串:[object + 結果(1)],格式為 [object Xxx] ,其中 Xxx 就是對象的類型。
對於 Object 對象,直接調用 toString() 就能返回 [object Object] 。而對於其他對象,則需要通過 call / apply 來調用才能返回正確的類型信息。
console.log(Object.prototype.toString.call(1)) console.log(Object.prototype.toString.call(1n)) console.log(Object.prototype.toString.call('123')) console.log(Object.prototype.toString.call(true)) console.log(Object.prototype.toString.call(undefined)) console.log(Object.prototype.toString.call(null)) console.log(Object.prototype.toString.call({})) console.log(Object.prototype.toString.call([])) console.log(Object.prototype.toString.call(function a() {})) console.log(Object.prototype.toString.call(Symbol())) console.log(Object.prototype.toString.call(Math)) console.log(Object.prototype.toString.call(JSON)) console.log(Object.prototype.toString.call(new Date())) console.log(Object.prototype.toString.call(new RegExp())) console.log(Object.prototype.toString.call(new Error)) console.log(Object.prototype.toString.call(window) console.log(Object.prototype.toString.call(document))封裝一個準確判斷數據類型的函數
function __getType(object){ return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1]; };可以解決上面的跨框架問題。
<script> window.onload=function(){ var iframe_arr=new window.frames[0].Array; console.log(Object.prototype.toString.call(iframe_arr))) }</script>本文完~
學習更多技能
請點擊下方公眾號