js中判斷數據類型的方法


typeof 、instanceof、constructor、jQuery.type()
1. typeof——返回對應的數據類型。
作用:區分基本數據類型
語法:typeof(變量名)

例:

var str = "我是字符串";
var num = 666;
var obj = new Object();
var arr = [1,2,3];
var fn = function(){
console.log("函數")
}
typeof(str) //string
typeof(num) //number
typeof(obj) //object
typeof(arr) //object
typeof(fn) //function

問題:如果是引用類型(復雜數據類型:對象和數組),那么返回的都是Object,無法具體區分

2. instanceof——只適用於對象類型,不適用於簡單類型的數據類型,返回boolean值
作用:1:識別對象類型;
2:判斷一個對象是否屬於某個構造函數的實例
語法:變量名 instanceof 數據類型 || 實例對象名 instaneof 構造函數

例1:只要是對象類型的都可以區分

arr instanceof Array //true
new Date() instanceof Date //true

例2:使用instanceof來檢驗F是否屬於構造函數fn的實例

var F = new fn(); //實例化構造函數
F instanceof fn ; //true,說明F是屬於fn的實例

問題:對於不同的構造函數,同一個實例都返回了true,如下F對Object同樣返回了true

F instanceof Object //true

instanceof原理:左邊是一個實例對象,右邊是一個構造函數,instanceof會檢查構造函數的原型對象prototype是否在左邊對象的原型鏈上,有則返回true,否則返回false.
instanecof內部執行函數:

instanceof (A,B) = {
var L = A.__proto__;
var R = B.prototype;
if(L === R) {
//A的內部屬性__proto__指向B的原型對象
return true;
}
return false;
}

那么我們來看下左邊對象的原型鏈以及右邊函數的原型對象上都發生了什么
F.__proto__===fn.prototype //true 實例化對象F的原型指向fn的原型對象
F.__proto__.proto__||fn.prototype.__proto__===Object.prototype //true fn的原型又指向Object的原型對象
Object.prototype.__proto__ //null

說明從F——fn——Object都在一條原型鏈上,其中fn和Object的prototype屬性都存在於F所在的這條原型鏈上,所以,F針對於兩個函數都返回了true

3.constructor——本身是prototype對象的一個屬性,默認指向prototype屬性所在的構造函數,此處我們用來判斷數據類型。返回boolean值
作用:1.判斷數據類型,包括數組、日期、對象等,可以區分清楚
語法:變量名.constructor === 數據類型

例:

str.constructor===String //true
num.constructor===Number //true
obj.constructor===Object //true
arr.constructor===Array //true
new Date().constructor===Date //true


4.jQuery.type()——稱之為萬能
作用:判斷數據類型。PS.其判斷的結果顯示都是小寫的字符串形式
語法:jQuery.type(變量名)

例:包括日期、正則、undefined、null等都是可以判斷的

jQuery.type(str) //string
jQuery.type(num) //number
jQuery.type(arr) //array
jQuery.type(obj) //object
jQuery.type(fn) //funtion

Javascript 中的數據類型判斷其實是一個JavaScript非常基礎問題,但不論是日常實際編程過程中和還是面試時,這都是一個非常常見的問題。

很多人被問到如何判斷一個變量數據類型這個問題時,大概都能回答上幾種方法,但是一深入的問題各種判斷方法的區別、優劣、局限、原理,卻一時半會理不清楚了,所以就借這一篇文章,復習一下JavaScript中這個基礎但很容易出錯的問題。

 

所以一般來說, typeof 會使用在比較簡單的場景, 一般用在你幾乎可以確定數據是哪一類數據然后稍微加以區分的時候。

舉個例子,比如你已經知道某個變量一定是JS的6種基本類型之一時,你可以用typeof加以區分;又比如你不需要知道明確的類型,你只是想判斷一個變量是不是對象或數組,這個時候也可以用typeof val === 'object'來判斷(當然你需要確保這個變量不是null)。

不得不吐槽一句,typeof null === 'object' 其實是JavaScript的一個bug,那么多個版本還一直不肯改過來......

instanceof

instanceof 其實適合用於判斷自定義的類實例對象, 而不是用來判斷原生的數據類型, 舉個例子:

// a.html
<script> var a = [1,2,3]; </script> // main.html <iframe src="a.html"></iframe> <script> var frame = window.frames[0]; var a = frame.a; console.log(a instanceof Array); // false  console.log(a.contructor === Array); //false  console.log(a instanceof frame.Array); // true </script>

是什么原因導致上面的結果呢? 其實 iframe 之間不會共享原型鏈, 因為他們有獨立的執行環境, 所以 frame a 中的數組 a 不會是本執行環境的實例對象. 通過特性嗅探同樣不靠譜, 像通過 contructor

Sort, slice 等等的特有的數組(或者其他數據類型)方法或屬性, 萬一對象中也有 sort, slice 屬性, 就會發生誤判. 所以最靠譜的方法是使用 Object.prototype.toString 方法.

Object.prototype.toString

在任何值上調用 Object 原生的 toString() 方法,都會返回一個 [object NativeConstructorName] 格式的字符串。
需要注意的是,但是它不能檢測非原生構造函數的構造函數名。

function foo(){}; Object.prototype.toString.call(1); '[object Number]' Object.prototype.toString.call(NaN); '[object Number]' Object.prototype.toString.call('1'); '[object String]' Object.prototype.toString.call(true); '[object Boolean]' Object.prototype.toString.call(undefined); '[object Undefined]' Object.prototype.toString.call(null); '[object Null]' Object.prototype.toString.call(Symbol());'[object Symbol]' Object.prototype.toString.call(foo); '[object Function]' Object.prototype.toString.call([1,2,3]); '[object Array]' Object.prototype.toString.call({});'[object Object]' 

從上面的例子可以看到,Object.prototype.toString 方法能有效彌補typeof不能很好區分數組、對象和函數的短板。

每個類在內部都有一個 [[Class]] 屬性,這個屬性中就指定了上述字符串中的構造函數名。

Object.prototype.toString 的原理是當調用的時候, 就取值內部的 [[Class]] 屬性值, 然后拼接成 '[object ' + [[Class]] + ']' 這樣的字符串並返回. 然后我們使用 call 方法來獲取任何值的數據類型.

constructor

console.log(bool.constructor === Boolean);// true  console.log(num.constructor === Number);// true  console.log(str.constructor === String);// true  console.log(arr.constructor === Array);// true  console.log(obj.constructor === Object);// true  console.log(fun.constructor === Function);// true  console.log(Symbol.constructor === Symbol);// true  console.log(haoxl.constructor === Student);// false  console.log(haoxl.constructor === Person);// true 

undefined和null沒有contructor屬性

constructor不能判斷undefined和null,並且使用它是不安全的,因為contructor的指向是可以改變的

有用的數據類型判斷函數

Array.isArray()
用於確定傳遞的值是否是一個Array。如果對象是Array,則返回true,否則為false。

Array.isArray([1, 2, 3]); // true Array.isArray({foo: 123}); // false Array.isArray("foobar"); // false Array.isArray(undefined); // false 

isNaN()和Number.isNaN
isNaN()函數用來確定一個值是否為 NaN。
注:isNaN函數內包含一些非常有趣的規則;
你也可以使用 ECMAScript 2015 中定義的Number.isNaN()來判斷。

與 JavaScript 中其他的值不同, NaN不能通過相等操作符(== 和 ===)來判斷 ,因為 NaN == NaN 和 NaN === NaN 都會返回 false。 因此,isNaN 就很有必要了。

isNaN(NaN); // true 

OK, 成功了,看似很完美,但是接着看以下例子

isNaN('A String'); // true  isNaN(undefined); // true  isNaN({}); // true 

會發現,很明顯不是 NaN 的 value 也被誤判成 NaN 了。

這個BUG已經存在了20年,從JavaScript最開始就一直存在。很明顯當初的設計者,在設計isNaN()的時候,局限了在 "Not a Number" 這一字面意思上了:只要不是number就會返回 true。

於是 ES6 為了彌補這一BUG(而不是修正,因為isNaN存在時間太長,有可能很多功能都是基於這個BUG之上的)引入了 Number.isNaN().

Number.isNaN(NaN); // true  Number.isNaN('A String'); // false  Number.isNaN(undefined); // false  Number.isNaN({}); // false 

沒有ES6的情況下,可以采用以下polyfill

if (!Number.isNaN) { Number.isNaN = function(n) { return ( typeof n === "number" && window.isNaN( n ) ); }; } 

判斷是否是 DOM 元素

在實際項目里面, 有時或許我們需要判斷是否是 DOM 元素對象, 那么在判斷的時候利用的是 DOM 對象特有的 nodeType 屬性:

isElement: function(obj){ return !!(obj && obj.nodeType === 1); } 

判斷是否是對象

isObject: function(obj){ var type = typeof obj; return type === 'function' || typeof === 'object' && obj !== null; } 

這里的對象是狹義的, 是通常所指的 key-value 型的集合, 或者是 function 函數並且不為 null.

判斷是否是 arguments 對象

判斷一個對象是不是 arguments 對象可以通過 Object.prototype.toString 來判斷, 但是低版本的瀏覽器不支持, 他們返回的是 [object Object], 所以需要兼容:

isArguments: function(obj){ return Object.prototype.toString.call(obj) === '[object Arguments]' || (obj != null && Object.hasOwnProperty.call(obj, 'callee')); } 

兼容做法原理是通過對象的 hasOwnProperty 方法來判斷對象是否擁有 callee 屬性從而判斷是不是 arguments 對象.

 


總結:
typeof()——判斷簡單的數據類型,無法菊粉復雜數據類型,例如像Object和Array返回的都是Object
instanceof ——僅適用於對象來區分數據類型。同時還可以判斷某個實例是否是某個構造函數的實例,但是會出現對應多個構造函數的情況
constructor——判斷所有的數據類型。當然他的本質是盤算prototyep屬性所在的函數的
jQuery.type()——判斷所有的數據類型。
原文鏈接:https://blog.csdn.net/baidu_41604826/article/details/89710303


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM