前语
当咱们在编写JavaScript代码时,了解和正确运用类型判别是非常重要的。JavaScript是一种弱类型言语,变量的类型能够动态改变,因而在处理数据时,咱们常常需求进行类型判别以保证代码的正确性和牢靠性。
本文将带领读者从根底到高级,深入分析JavaScript中的类型判别机制,揭开这一重要主题的面纱。
数据类型
JavaScript有七种原始数据类型与四种引证类型,原始数据类型分别是Undefined、Null、Boolean、Number、String、Symbol和BigInt,引证类型分别是目标、数组、函数、日期。
1. typeof
在进行类型判别时,咱们能够运用typeof
操作符来获取变量的类型。
原始数据类型
let str = 'hello';
console.log(typeof str); // "string"
let num = 123;
console.log(typeof num); // "number"
let flag = true;
console.log(typeof flag); // "boolean"
let und = undefined;
console.log(typeof und); // "undefined"
let nu = null;
console.log(typeof nu); // "object"
let big = 123n;
console.log(typeof big); // "bigint"
let s = Symbol('hello');
console.log(typeof s); // "symbol"
引证类型
let obj = {};
console.log(typeof obj); // "object"
let arr = [];
console.log(typeof arr); // "object"
let fn = function(){};
console.log(typeof fn); // "function"
let date = new Date();
console.log(typeof date); // "object"
咱们发现typeof null
回来的是object
,这是一个前史遗留问题,与言语本身的设计和演化有关。在 JavaScript 的前期版别中,变量的值是由存储在变量存储空间中的符号位来表明的。在 JavaScript 中,一切的目标都表明为32位的字(words),而其中的第一个位被用作类型标签。
- 目标类型的类型标签是
000
。null
被认为是一个空目标指针,因而它的类型标签也是000
。
因而,typeof null
回来 "object"
是因为在查看变量类型时,JavaScript 会读取存储在变量存储空间中的类型标签,而 null
的类型标签被解释为目标类型。
虽然这个行为是前史遗留问题,但为了保持向后兼容性,JavaScript 的设计者挑选保留了这个特性。在现代的 JavaScript 中,为了准确判别变量是否为 null
,引荐运用严厉相等运算符 ===
:
console.log(nu === null) //true
除此之外,咱们发现引证类型只能将函数判别为function
、将目标判别为object
,而数组跟函数也判别为object
。所以咱们还需求再找一个能进一步判别引证类型的操作符。
2. instanceof
instanceof
操作符用于查看目标是否是特定类(结构函数)的实例。它经过查看目标的原型链来确定目标的类型。假如目标是指定类的实例,则回来 true
,否则回来 false
。
let obj = {}
console.log(obj instanceof Object); // true
let arr = []
console.log(arr instanceof Array); // true
let fn = function(){}
console.log(fn instanceof Function); // true
let date = new Date()
console.log(date instanceof Date); // true
所以咱们能够经过instanceof
,再结合结构函数来判别引证类型。
于是咱们能够手写一个instanceof
:
function instanceOF(L, R) {
let left = L.__proto__; // 初始化变量 left 为实例目标 L 的隐式原型
let right = R.prototype; // 初始化变量 right 为结构函数 R 的显现原型
while (left !== null) { // 迭代访问左操作数的原型链,假如不为空则进循环
if (left === right) { // 查看当时目标的隐式原型是否与结构函数的显现原型相等
return true; // 假如相等,回来 true,表明这个实例目标是这个结构函数创建的
}
left = left.__proto__; // 移动到链中的下一个隐式原型
}
return false; // 假如没有找到匹配,回来 false
}
//举例:
console.log(instanceOF([],Array));//true
但是咱们在运用instanceof
的时候,还会呈现一种情况:
let arr = []
console.log(arr instanceof Object); // true
咱们发现,数组也能够被判定为目标,所以当咱们要判别一个数据类型是不是目标的时候,用instanceof
就不当,因为数组能够被辨认成目标。导致咱们判别过错。
那有没有能够直接判别类型的办法?
3. Object.prototype.toString()
官方定义:
Object.prototype.toString()
当调用toString
办法时,将执行以下步骤:
- 假如
this
值未定义,则回来"[object undefined]"
。- 假如
this
值为空,则回来"[object null]"
。- 让
o
作为传递this
值作为参数的object
调用的成果。- 设
class
为o
的内部特点[[Class]]
的值。- 回来三个字符串
"[object "
和class
和"]"
衔接后的String
值。
以上为官方规定,在这里就不过多解释,咱们直接用就行了。(参阅原文Annotated ES5)
let number = 42;
console.log(Object.prototype.toString.call(number)); // "[object Number]"
let str = "Hello";
console.log(Object.prototype.toString.call(str)); // "[object String]"
let bool = true;
console.log(Object.prototype.toString.call(bool)); // "[object Boolean]"
console.log(Object.prototype.toString.call(null));//'[object Null]'
console.log(Object.prototype.toString.call(undefined));//'[object Undefined]'
let bigint = 123n
console.log(Object.prototype.toString.call(bigint));//'[object BigInt]'
let symbol = Symbol('hello')
console.log(Object.prototype.toString.call(symbol));//'[object Symbol]'
let array = [];
console.log(Object.prototype.toString.call(array)); // "[object Array]"
let date = new Date();
console.log(Object.prototype.toString.call(date)); // "[object Date]"
var obj = {};
console.log(Object.prototype.toString.call(obj));//'[object Object]'
let func = function() {};
console.log(Object.prototype.toString.call(func)); // "[object Function]"
咱们能够用这个办法判别然后数据类型。在这里咱们经过运用 call
办法,能够将 this
设置为任何咱们想要查看的目标,从而获取该目标的准确类型信息。
咱们能够稍加改善,让这个办法更简单为咱们所用:
var s ='thisisstring'
function isType(s) {
return Object.prototype.toString.call(s).slice(8,-1)
}
if(isType === 'String'){
//xxx
}
经过isType
函数,咱们就能够获取变量 s
的类型,并与字符串 'String'
进行比较,其中slice(8,-1)
用于截取类型字符串,去除 "[object "
和 "]"
部分。
最终
经过本文的学习,咱们不只深入了解了基本的 typeof
操作符和 instanceof
操作符,还探讨了更为精准的 Object.prototype.toString
办法。这些工具不只协助咱们在编码进程中避免潜在的过错,还为处理各种杂乱的数据结构供给了牢靠的手段。
我的Gitee: CodeSpace (gitee.com)
技术小白记录学习进程,有过错或不解的当地还请谈论区留言,假如这篇文章对你有所协助请 “点赞 保藏 重视”,感谢支持!!