一、概念
1. typeof是一个运算符,有2种使用方式:typeof(表达式)和typeof 变量名,第一种是对表达式做运算,第二种是对变量做运算。typeof 操作符返回一个字符串,表示未经计算的操作数的类型。
可能的返回值:
- “undefined”
- “object”
- “boolean”
- “number”
- “bigint”
- “string”
- “symbol”
- “function”
注意:
typeof null === 'object';
查阅了相关的资料,其实这个是一个历史遗留的bug,在 javascript 的最初版本中,使用的 32 位系统,为了性能考虑使用低位存储了变量的类型信息:
- 000:对象
- 010:浮点数
- 100:字符串
- 110:布尔
- 1:整数
但是, 对于 undefined
和 null
来说,这两个值的信息存储是有点特殊的。
null
:对应机器码的 NULL 指针,一般是全零。
undefined
:用 −2^30 整数来表示!
所以,typeof
在判断 null
的时候就出现问题了,由于 null
的所有机器码均为0,因此直接被当做了对象来看待。
2.instanceof 运算符用于检测构造函数的 prototype
属性是否出现在某个实例对象的原型链上。
语法:
object instanceof constructor
// object 某个实例对象
// construtor 某个构造函数
3.Object.prototype.toString()
var toString=Object.prototype.toString;
console.log(toString.call(ndefined)); // [object Undefined]
console.log(toString.call(null)); // [object Null]
console.log(toString.call(true)); // [object Boolean]
console.log(toString.call(666)); // [object Number]
console.log(toString.call('前端收割机')); // [object String]
console.log(toString.call({})); // [object Object]
console.log(toString.call([])); // [object Array]
console.log(toString.call(function(){})); // [object Function]
console.log(toString.call(new Date)); // [object Date]
console.log(toString.call(new RegExp)); // [object RegExp]
console.log(toString.call(new Error)); // [object Error]
console.log(toString.call(arguments)); // [object Arguments]
二、实现
1.优化版本typeof
console.log(typeof 6) //输出 number
console.log(typeof null) //输出 object
console.log(typeof {}) //输出 object
console.log(typeof []) //输出 object
console.log(typeof (new Date)) // 输出 object
console.log(typeof (function(){})) //输出 function
console.log(typeof undefined) //输出 undefined
console.log(typeof '前端收割机') //输出 string
console.log(typeof true)//输出 boolean
由上可得,typeof
可以正确识别Undefined、Boolean、Number、String、Symbol、Function
等数据类型,但是在数组,日期,对象上的判断确并不准确,都是返回object
优化版本实现代码:
/*
实现思路:
1.利用Object.prototype.toString()方法
2.将Object.prototype.toString()方法获取的字符串进行截取
3.利用toLowerCase()方法,将字符串转为小写
*/
function typeOf(obj) {
return Object.prototype.toString.call(obj).slice(8,-1).toLowerCase();
}
typeOf([]); // 输出 array
typeOf({}); // 输出 object
typeOf(new Date); // 输出 date
2.实现instanceof
/*
实现思路:
1.leftVaule代表实例对象
2.rightVaule代表构造函数
3.利用typeof方法,判断输入的leftVaule是否为对象,如果不是,则返回false
4.遍历leftVaule的原型链,直到找到rightVaule的prototype,如果查找失败的话,返回false,反之,返回true
*/
function my_instanceof(leftVaule, rightVaule) {
if(typeof leftVaule !== 'object' || leftVaule === null) return false;
let rightProto = rightVaule.prototype,
leftProto = leftVaule.__proto__;
while (true) {
if (leftProto === null) {
return false;
}
if (leftProto === rightProto) {
return true;
}
leftProto = leftProto.__proto__
}
}
只要右边变量的prototype在左边变量的原型链上及可,也就是返回true。因此,instanceof
在查询的过程中会遍历左边变量的原型链,直到找到右边变量的prototype
,如果查找失败的话,返回false
,告诉我们左边的变量并非是右边变量的实例。
三、总结
- 使用
typeof
来判断基本数据类型是ok
的,需要注意的是typeof
判断null类型时的问题 - 判断一个对象的话具体考虑用
instanceof
,但是instanceof
判断一个数组的时候,它可以被instanceof
判断为Obeject
- 比较准确的的判断对象实例的类型,采取
Object.prototype.toString.call()
方法
参考连接:https://juejin.cn/post/6844904199700873223#heading-6