js类型判断,类型转换及经典面试题

49 阅读4分钟

js中的基本类型

基本类型:number(只可以表示2的53次方-1),string,boolean,undefined,null,symbol,bigint(基于数组方式表示)

引用类型:Object, Array, Function, Date, RegExp, Map/Set/WeakMap/WeakSet (ES6+)

判断js的类型有以下几种方法

一、typeof判断法(基本类型判断)

image.png 通过上面的输出我们可以发现:typeof可以判断除了null以外的其他类型基本数据, typeof判断引用数据类型,除了function 以外,其他的都返回object。

实现原理:typeof是通过将值的转化为二进制数来判断类型的,二进制的前三位为0那么就识别为对象,null的二进制全是0故判断为对象类型。

二、Instanceof(引用类型判断)

在理解 instanceof 之前,必须明确两个关键概念:

1.显式原型 (prototype):

  • 是构造函数特有的属性
  • 指向该构造函数创建的实例对象的原型对象
  • 例如:Array.prototype 是所有数组实例的原型

2.隐式原型 (proto):

  • 是每个对象都有的属性
  • 指向创建该对象的构造函数的 prototype
  • 现代代码中建议使用 Object.getPrototypeOf() 替代 proto

image.png

Instanceof方法本质上是判断左边的隐式原型是不是右边的显示原型。如果不是则继续判断左边隐式原型的隐式原型,一直判断下去,直到两边相等或者左边的值已经为null了。嘿嘿嘿,都知道原理了手搓一个代码不过分吧。

手搓Instanceof方法

function myInstanceof(L,R){
    L=L.__proto__
    while(L){
        if(L==R.prototype){
            return true
        }
        L=L.__proto__
    }
    return false

三、Object.prototype.toString(任何类型)

Object.prototype.toString( ) 是 JavaScript 中用于检测对象类型的核心方法。它可以精确返回任意值的内部 [[Class]] 属性(格式为 [object Type])。

image.png

与 typeof 和 instanceof 的对比

方法特点
typeof无法区分对象类型(如 ArrayDate 均返回 "object"
instanceof受原型链影响,跨窗口/iframe 时会失效
Object.prototype.toString最可靠,能精确识别内置类型(包括 Null 和 Undefined

小小判断题

在进一步了解我们的判断之前我们先区分一下==与====

1.==会发送隐式类型转化,所以只判断值是不是相等的

2.===不会发生类型转化,所以只会判断值和类型是不是相等的

image.png

这是因为==发生的隐式转化,所以只判断值是否相等,故第一个输出的结果为true,但是第二个===不发生类型转化,数字类型与string类型显然是不相等的嘛。

隐式转化与显式转化

通俗的来说隐式转化也就是我们看不到的类型转化,由js引擎自动完成,开发者不直接转换代码。 显示转化也就是写出来的转化,是开发者主动调用的类型转化。引用类型可以转化为原始类型 这个是基于目的来的,因为我们的判断主要是四则运算这些,四则运算又是判断基本的数据类型。 但是原始类型是不可以转化为引用类型的

一、原始类型转原始类型

image.png

valueOf()

出现在对象的原型上面,只能将包装类的对象转化为原始类型。

toString()

js中的大部分构造函数原型上面都重写了toString方法
  1. {}.toString返回由
  2. [].toString 返回由数组中的每个元素以逗号拼接而成的字符串
  3. xxx.toString 直接返回xxx的字符串字面量

二、引用类型转原始类型

1. 转布尔----任何引用类型转布尔都是true

image.png

2.转字符串--Stirng(obj)==>ToString(obj)==>Toprimitive(obj,string)

Toprimitive(obj,string)

  1. 判断obj是否为原始数据类型,若是则直接返回
  2. 否则,调用toString(),如果得到的是原始类型则返回
  3. 否则,调用valueOf(),如果的到的是原始类型则返回
  4. 否则,抛出TypeError的错误

3.转数字——Number(obj)==>ToNumber(obj)==>Toprimitive(obj,Number)

Toprimitive(obj,Number)

  1. 判断obj是否为原始数据类型,若是则直接返回
  2. 否则,调用valueOf(),如果的到的是原始类型则返回
  3. 否则,调用toString(),如果得到的是原始类型则返回
  4. 否则,抛出TypeError的错误

经典面试题

console.log(1==[]);

类型不同触发隐式转换
比较 number == array,需要将数组转为原始值
执行 ToPrimitive([], 'number')
检查 Symbol.toPrimitive:数组没有定义 → 跳过
调用 valueOf():[].valueOf() 返回数组本身(非原始值)→ 继续
调用 toString():[].toString() 返回空字符串 ""
得到 Number("")
空字符串转为数字是 0
最终比较 1 == 0
结果为 false

console.log([]==![]);

![] 取反运算
[] 在布尔上下文中转为 true(所有对象转布尔都是 true)
!true 结果为 false
现在表达式变为:[] == false
false 转数字
根据规则:boolean 在 == 比较时会先转 number
Number(false) → 0
现在表达式变为:[] == 0
[] 转原始值
调用 [].valueOf() → 返回 [](仍是对象,继续转换)
调用 [].toString() → 返回 ""(空字符串)
现在表达式变为:"" == 0
"" 转数字
Number("") → 0
最终比较:0 == 0true