欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JS必備技能之?dāng)?shù)據(jù)類型判斷與底層原理深入解析

 更新時(shí)間:2025年09月22日 08:31:20   作者:努力的小朱同學(xué)  
在JavaScript中類型判斷是指確定一個(gè)變量或值的類型的過(guò)程,這篇文章主要介紹了JS必備技能之?dāng)?shù)據(jù)類型判斷與底層原理的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下

一、簡(jiǎn)介

? 精準(zhǔn)判斷數(shù)據(jù)類型是每一位前端開發(fā)者的必備技能,但 JS 因存在基礎(chǔ)類型與引用類型的區(qū)分以及歷史遺留問(wèn)題等,單一判斷方式往往無(wú)法覆蓋所有場(chǎng)景。本文梳理并解析了 5 類常用的數(shù)據(jù)類型判斷方法,包括:基礎(chǔ)類型常用的 typeof、對(duì)象類型專屬的 instanceof 、全類型通用的 Object.prototype.toString.call()、基于構(gòu)造函數(shù)引用的 constructor,以及針對(duì)數(shù)組、NaN、整數(shù)等場(chǎng)景的特定判斷方案。

基礎(chǔ)類型:

String、Number、Boolean、Null、Undefined、Symbol、bigint(ES2020新增)。

這些類型的數(shù)據(jù)占據(jù)的空間較小且大小是固定的,因此數(shù)據(jù)直接存儲(chǔ)在棧(stack)內(nèi)存中,方便頻繁調(diào)用數(shù)據(jù)。

引用類型:

? Object(包含Array、Function、Date、RegExp、Map、Set等等)。

? 該類型的數(shù)據(jù)占據(jù)的空間較大且大小不固定,是將數(shù)據(jù)存儲(chǔ)在堆(heap)內(nèi)存中,并在棧(stack)內(nèi)存中存儲(chǔ)一個(gè)引用指針,該指針指向當(dāng)前數(shù)據(jù)在堆中的實(shí)際空間地址。

二、具體方案

1、typeof

? typeof 運(yùn)算符常用于獲取基礎(chǔ)數(shù)據(jù)的類型,可以獲取到一個(gè)表示數(shù)據(jù)的類型的字符串,類型字符串有:number、string、boolean、object、function、undefined、symbol、bigint。

? typeof 運(yùn)算符在遇到除 null 之外基礎(chǔ)類型的數(shù)據(jù),都能正常獲取其類型字符串(number、string等),而遇到 null 會(huì)返回 object ,這是由于歷史遺留問(wèn)題。但遇到對(duì)象類型數(shù)據(jù),其判斷結(jié)果具有局限性,遇到函數(shù)則會(huì)返回 function ,而遇到其他對(duì)象(如對(duì)象、數(shù)組、日期等)都只會(huì)返回 object,因此無(wú)法區(qū)分具體對(duì)象類型。

基本語(yǔ)法:

typeof 數(shù)據(jù)

判斷原理:

? JS中的數(shù)據(jù),在底層中都是以二進(jìn)制的形式存儲(chǔ)的,并且會(huì)通過(guò)低位的 “類型標(biāo)簽”(tag) 來(lái)區(qū)分不同數(shù)據(jù)類型,不同的JS引擎具體實(shí)現(xiàn)不同,比如V8引擎中:二進(jìn)制000結(jié)尾-表示對(duì)象類型、二進(jìn)制1結(jié)尾-表示整數(shù)類型等等。typeof 的原理就是通過(guò)底層標(biāo)簽來(lái)判斷數(shù)據(jù)的類型,而特殊的null,其所有二進(jìn)制位都是 0 ,所以引擎會(huì)將以 000 結(jié)尾的標(biāo)簽將其誤判為 object。

使用示例:

// 數(shù)字類型
typeof 37 === 'number';
typeof 3.14 === 'number';
typeof Math.LN2 === 'number';
typeof Infinity === 'number';
typeof NaN === 'number'; // 盡管NaN是非數(shù)字的意思
typeof Number(1) === 'number'; // 但不建議使用!

// bigInt
typeof 42n === 'bigint'; 

// 字符串類型
typeof "" === 'string';
typeof "bla" === 'string';
typeof (typeof 1) === 'string'; // typeof返回的是字符串
typeof String("abc") === 'string'; // 但不建議使用!

// 布爾類型
typeof true === 'boolean';
typeof false === 'boolean';
typeof Boolean(true) === 'boolean'; // 但不建議使用!

// Symbol類型
typeof Symbol() === 'symbol';
typeof Symbol('foo') === 'symbol';
typeof Symbol.iterator === 'symbol';

// Undefined
typeof undefined === 'undefined';
var a // 聲明但未賦值
typeof a === 'undefined';
typeof b === 'undefined'; // 未聲明未賦值

// 對(duì)象類型
typeof {a:1} === 'object';
typeof [1, 2, 4] === 'object'; // 數(shù)組會(huì)被判斷為對(duì)象
typeof new Date() === 'object';
typeof null === 'object'; // null 也會(huì)被判斷為對(duì)象

// 函數(shù)
typeof function(){} === 'function';
typeof Math.sin === 'function';

2、instanceof

? instanceof 運(yùn)算符常用于判斷對(duì)象數(shù)據(jù)的具體數(shù)據(jù)類型,可以判斷一個(gè)對(duì)象數(shù)據(jù)是否為某個(gè)構(gòu)造函數(shù)的實(shí)例,返回一個(gè)布爾值。

? instanceof 運(yùn)算符不適用于基礎(chǔ)數(shù)據(jù)類型(包括null),但適用于基礎(chǔ)類型的包裝對(duì)象。并且如果判斷數(shù)組、函數(shù)等具體對(duì)象數(shù)據(jù)是否為 Object 類型,結(jié)果也會(huì)是true,因?yàn)?Object 類型屬于最外層的大類型。因此想要判斷具體的對(duì)象類型,需要精準(zhǔn)的判斷,不能用排除法。

? 由于原型鏈?zhǔn)强梢员恍薷牡?,因此判斷結(jié)果并非絕對(duì)可靠。

基本語(yǔ)法:

對(duì)象 instanceof 構(gòu)造函數(shù)

判斷原理:

? JS中對(duì)象數(shù)據(jù)存在原型鏈,instanceof 就是通過(guò)沿著左邊對(duì)象的原型鏈向上查找,如果在左邊對(duì)象的原型鏈上存在右邊構(gòu)造函數(shù)的 prototype ,則說(shuō)明左邊對(duì)象是右邊構(gòu)造函數(shù)的實(shí)例,也就是說(shuō)左邊對(duì)象屬于右邊構(gòu)造函數(shù)的類型,返回 true,否則返回 false。

? 因此該方案只適用于同一個(gè)全局環(huán)境下的判斷,因?yàn)樵诓煌娜汁h(huán)境(如iframe)中,構(gòu)造函數(shù)的 prototype 指向的是不同的對(duì)象,會(huì)導(dǎo)致判斷錯(cuò)誤。

使用示例:

// 數(shù)組
var a = [1,2,3]
console.log(a instanceof Array)  // true
console.log(a instanceof Object) // true,兩者都成立
var a2 = new Array
console.log(a2 instanceof Array)  // true
console.log(a2 instanceof Object) // true

// 函數(shù)(包括箭頭函數(shù))
var b = function() {}
console.log(b instanceof Function) // true
console.log((()=>{}) instanceof Function) // true 
console.log(b instanceof Object)  // true

// 對(duì)象
var c = {}
console.log(c instanceof Object) // true
console.log(Date instanceof Object) // true

// 內(nèi)置對(duì)象
var str = new String()
str instanceof String // true
var myDate = new Date()
myDate instanceof Date;     // true
myDate instanceof Object;   // true

// 基礎(chǔ)數(shù)據(jù)的包裝類
const numObj = new Number(123);
numObj instanceof Number; // true(包裝對(duì)象可被判斷)
123 instanceof Number; // false(原始值不可被判斷)

3、Object.prototype.toString.call()

? Object.prototype.toString.call() 方法可用于判斷所有數(shù)據(jù)的具體類型,可以獲取到一個(gè)表示數(shù)據(jù)具體類型的標(biāo)準(zhǔn)字符串,返回格式為: [object Xxxx],其中 Xxxx 就是數(shù)據(jù)的具體類型,無(wú)論是基本數(shù)據(jù)類型還是對(duì)象數(shù)據(jù)類型,都能精準(zhǔn)的區(qū)分。

基本語(yǔ)法:

Object.prototype.toString.call(數(shù)據(jù));

判斷原理:

? 每個(gè)JS內(nèi)置對(duì)象都有一個(gè)內(nèi)部屬性 [[Class]](抽象概念,無(wú)法直接訪問(wèn)),其值為該對(duì)象的類型標(biāo)識(shí)(如 Array、Date、Number、String 等)。當(dāng)調(diào)用 Object 原型上的 toString() 方法,并通過(guò) call() 方法改變this的指向到目標(biāo)數(shù)據(jù)時(shí),對(duì)于對(duì)象類型數(shù)據(jù),該方法會(huì)直接讀取目標(biāo)數(shù)據(jù)的 [[Class]] 屬性,并返回對(duì)應(yīng)類型字符串 [object [[Class]]];對(duì)于基本類型數(shù)據(jù), call() 方法會(huì)先自動(dòng)將其轉(zhuǎn)換為對(duì)應(yīng)的包裝對(duì)象,再讀取其 [[Class]] 屬性,最后返回對(duì)應(yīng)類型字符串 [object [[Class]]]。

使用示例:

Object.prototype.toString.call(123);         // "[object Number]"
Object.prototype.toString.call('abc');       // "[object String]"
Object.prototype.toString.call(true);        // "[object Boolean]"
Object.prototype.toString.call(null);        // "[object Null]"
Object.prototype.toString.call(undefined);   // "[object Undefined]"
Object.prototype.toString.call([1, 2]);      // "[object Array]"
Object.prototype.toString.call(new Date());  // "[object Date]"
Object.prototype.toString.call(/abc/);       // "[object RegExp]"
Object.prototype.toString.call(function(){}); // "[object Function]"
Object.prototype.toString.call({});          // "[object Object]"
Object.prototype.toString.call(Symbol());    // "[object Symbol]"
Object.prototype.toString.call(123n); // "[object BigInt]"
Object.prototype.toString.call(new Map()); // "[object Map]"
Object.prototype.toString.call(new Set()); // "[object Set]"
Object.prototype.toString.call(new WeakMap()); // "[object WeakMap]"

4、constructor

? constructor 常用于判斷對(duì)象的具體類型,其是對(duì)象的一個(gè)屬性,它指向創(chuàng)建該對(duì)象的構(gòu)造函數(shù),通過(guò)與特定的構(gòu)造函數(shù)進(jìn)行比較,區(qū)分對(duì)象的具體類型。

? 對(duì)于除 null、undefined 之外基礎(chǔ)類型數(shù)據(jù),在其調(diào)用 constructor 屬性時(shí),JS會(huì)自動(dòng)進(jìn)行“裝箱”操作,將其臨時(shí)變?yōu)閷?duì)應(yīng)的包裝對(duì)象,從而擁有 constructor 屬性;對(duì)于null、undefined,它們沒(méi)有對(duì)應(yīng)的包裝對(duì)象,因此無(wú)法調(diào)用 constructor。

? 由于 constructor 屬性是可以被修改的,因此判斷結(jié)果并非絕對(duì)可靠。

基本語(yǔ)法:

數(shù)據(jù).constructor === 構(gòu)造函數(shù)

判斷原理:

? JS中每個(gè)對(duì)象在創(chuàng)建時(shí)都會(huì)關(guān)聯(lián)一個(gè)構(gòu)造函數(shù),constructor 屬性就是對(duì)這個(gè)構(gòu)造函數(shù)的引用。例如,數(shù)組是由 Array 構(gòu)造函數(shù)創(chuàng)建的,所以數(shù)組的 constructor 屬性指向 Array;日期對(duì)象由 Date 構(gòu)造函數(shù)創(chuàng)建,其 constructor 屬性指向 Date。因此,通過(guò)比較對(duì)象的 constructor 與對(duì)應(yīng)的構(gòu)造函數(shù),就能判斷出對(duì)象的具體類型。

使用示例:
// 基礎(chǔ)數(shù)據(jù)類型(除 null、undefined 外,通過(guò)包裝對(duì)象實(shí)現(xiàn))
(123).constructor === Number; // true
// 等價(jià)于
Number(123).constructor === Number;

'abc'.constructor === String; // true
// 等價(jià)于
String('abc').constructor === String;

true.constructor === Boolean; // true
// 等價(jià)于

// 引用數(shù)據(jù)類型
[1, 2].constructor === Array; // true(可識(shí)別數(shù)組)
new Date().constructor === Date; // true(可識(shí)別日期對(duì)象)
({}).constructor === Object; // true

5、特定類型判斷

① Array.isArray()

? 判斷數(shù)據(jù)是否為數(shù)組類型。

var arr = []
Array.isArray(arr); // true

② ===

? 準(zhǔn)確判斷 null 和 undefined。

let a = null;
a === null; // true

let b = undefined;
b === undefined; // true

a === b; // false

③ Number.isNaN()

? 判斷數(shù)據(jù)是否為NaN。該方法不會(huì)將參數(shù)強(qiáng)制轉(zhuǎn)換為數(shù)字類型,會(huì)直接判斷傳入的參數(shù)是否是 NaN,而全局的 isNaN() 方法會(huì)強(qiáng)制轉(zhuǎn)換參數(shù)為數(shù)字,導(dǎo)致非NaN值被誤判,因此更推薦使用 Number.isNaN()。

let n = NaN;
Number.isNaN(n); // true

④ Number.isInteger()

? 判斷數(shù)據(jù)是否為整數(shù)。

Number.isInteger(1); // true
Number.isInteger(1.2); // false
Number.isInteger(1.00); // true

三、 總結(jié)

? 沒(méi)有萬(wàn)能的方法,只有最適合當(dāng)前場(chǎng)景的方法。

判斷方法適用場(chǎng)景關(guān)鍵局限精準(zhǔn)度
typeof基礎(chǔ)類型(除 null)、函數(shù)快速判斷null 誤判為 object,無(wú)法區(qū)分?jǐn)?shù)組 / 日期等對(duì)象基礎(chǔ)類型高,引用類型低
instanceof引用類型(數(shù)組、日期等)的實(shí)例判斷不支持原始基礎(chǔ)類型,原型鏈修改會(huì)導(dǎo)致誤判引用類型較高(需注意全局環(huán)境)
Object.prototype.toString.call()所有類型(基礎(chǔ) + 引用)精準(zhǔn)判斷語(yǔ)法相對(duì)繁瑣,需處理返回的標(biāo)準(zhǔn)格式字符串最高(全場(chǎng)景通用)
constructor基礎(chǔ)類型(除 null/undefined)、引用類型判斷constructor 可被修改,null/undefined 無(wú)該屬性較高(需警惕屬性篡改)
特定判斷單一類型(數(shù)組、NaN、整數(shù)等)精準(zhǔn)校驗(yàn)適用范圍窄,僅針對(duì)特定場(chǎng)景極高(場(chǎng)景專屬)

總結(jié)

到此這篇關(guān)于JS必備技能之?dāng)?shù)據(jù)類型判斷與底層原理的文章就介紹到這了,更多相關(guān)JS數(shù)據(jù)類型判斷與底層原理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論