likes
comments
collection
share

面试官:请你谈谈JS中几种常见的类型判断方法

作者站长头像
站长
· 阅读数 26

前言

在开发的过程中,经常会遇到数据类型判断的场景,在JavaScript中常见的对类型进行判断的方法有:typeof、instance、Object.prototype.toString。在js中这些方法都能够判断数据类型,但是这些方法的实现原理和适用场景各不相同,本文我将带大家深入探讨它们的使用方法和底层原理。

typeof

我们知道,在JavaScript中数据分为两大类--原始数据类型和引用数据类型。

typeof判断原始数据类型

使用typeof判断原始数据类型时,可以判断除null之外的所有原始类型。

如以下示例代码:

// 原始数据类型
let s = '123'; // String
let n = 123; // number
let f = true; // boolean
let u = undefined; // undefined
let nu = null; // null

// es6新增的
// 创建一个独一无二的值
let sy = Symbol(123) // symbol
// 大整形数
let big = 1234n; // bigint


console.log(typeof s); // string
console.log(typeof n); // number
console.log(typeof f); // boolean
console.log(typeof nu); // object
console.log(typeof sy); // symbol
console.log(typeof big); // bigint

注意看。为什么使用typeof判断null的数据类型时输出的是object?其实这是一个历史遗留问题,在很早以前,计算机底层执行typeof是通过将值转化为二进制后判断其二进制前位是否为0来判断是不是object,当提出null时判断位数已经用完,所以null就被归为object那类。

typeof判断引用数据类型

使用typeof判断引用数据类型时,除了function其他所有的引用类型都会被判断成object

// 引用数据类型
let obj = {}
let arr = []
let fn = function () { }
let date = new Date()

console.log(typeof obj); // object
console.log(typeof arr);    // object
console.log(typeof fn); // function
console.log(typeof date); // object

instanceof

JavaScript中,可以使用instanceof来判断引用数据类型,不能用来判断原始数据类型。下面我将来为大家介绍instanceof判断数据类型的使用方法以及instanceof的底层原理。

instanceof的使用方法

let obj = {}
let arr = []
let fn = function () { }
let date = new Date()
let s = '123'; // String
let num = 123;
let bool = true;
// 引用数据类型的判断
console.log(obj instanceof Object); // true
console.log(arr instanceof Array); // true
console.log(fn instanceof Object); // true
console.log(fn instanceof Function); // true
console.log(date instanceof Object);// true

console.log("-----------------------")
// 原始数据类型的判断
console.log(s instanceof String); // false
console.log(num instanceof Number); // false
console.log(bool instanceof Boolean); //false

instanceof 不能直接用来判断 JavaScript 中的原始数据类型(也称为基本数据类型),如 stringnumberbooleanundefinednullsymbol 和 bigintinstanceof 操作符是用来检查一个对象是否在一个构造函数的原型链上,即判断一个对象是否是某个构造函数的实例。

原始数据类型不是对象,它们不是通过构造函数实例化产生的,因此没有原型链的概念,所以使用 instanceof 判断原始数据类型会始终返回 false

instanceof的底层原理

instanceof 的实现原理基于 JavaScript 的原型链。它的主要作用是检查一个对象是否在另一个对象的原型链上,也就是说,它会查看一个对象的原型是否等于或继承自另一个对象的原型。具体步骤如下:

  1. 获取右操作数的原型: 首先,instanceof 获取右侧构造函数(通常是类或函数)的 .prototype 属性,这个属性通常是一个对象,代表了实例化后的对象将继承的属性和方法。

  2. 遍历左操作数的原型链: 接着,instanceof 开始从左侧对象的 __proto__ 属性开始(在严格模式下,某些环境可能会使用 Object.getPrototypeOf 函数来获取原型),__proto__ 指向了该对象的构造函数的原型。

  3. 比较原型: 然后,instanceof 检查当前对象的原型是否等于右侧构造函数的原型。如果相等,返回 true,表示左侧对象是右侧构造函数的实例。如果不等,则继续沿着左侧对象的原型链向上查找,通过检查 __proto__ 的 __proto__,直到找到 null(表示到达原型链的顶部),此时返回 false

  4. 处理特殊情况

    • 如果左侧对象是 nullinstanceof 返回 false,因为 null 没有原型。
    • 如果右侧不是一个函数,instanceof 通常会抛出错误,因为只有函数才能有 .prototype

上述步骤为instanceof的底层实现原理,大家看起来是不是有点懵?接下我将用代码的形式手写instanceof的实现原理并用图文的形式给大家展示。

手写instanceof,请思考以下代码(从原型链的角度思考):

// instanceof 的原理
function myinstanceof(L, R) {
    while (L != null) {
        if (L.__proto__ === R.prototype) {
            return true;
        }
        L = L.__proto__;
    }
    return false;
}

myinstanceof([], Array) // true
myinstanceof([], Object) // true

面试官:请你谈谈JS中几种常见的类型判断方法

执行过程:

  1. 初始化L 同样是一个空数组实例,R 是 Object 构造函数。
  2. 原型链遍历:数组的直接原型 L.__proto__ 是 Array.prototype,但这不等于 Object.prototype。因此,继续向上遍历。
  3. 找到关联Array.prototype 的 __proto__ 是 Object.prototype,这意味着数组的原型链最终指向了 Object.prototype。因此,满足条件,返回 true。这表明所有数组(以及大多数JavaScript对象)也是 Object 的实例,因为它们继承自 Object.prototype

Object.prototype.toString.call(this)

Object.prototype.toString.call(this) 是 JavaScript 中一种常用的技巧,用于获取当前上下文(this)的精确类型表示。这个表达式的工作原理和用途如下:

原理

  1. Object.prototype.toString 方法

    • toString 方法是每个 JavaScript 对象从 Object.prototype 继承而来的方法。默认情况下,当直接调用一个对象的 toString 方法时(例如,obj.toString()),它会返回一个表示该对象的字符串。对于普通对象,这通常是 [object Object]

面试官:请你谈谈JS中几种常见的类型判断方法

  1. 覆盖与默认行为

    • 许多内置对象(如数组、函数、日期等)重写了 toString 方法,以提供更有用的信息。但是,这些重写的版本通常关注于对象的内容,而不是其类型。
  2. Object.prototype.toString 的特殊性

    • 特别地,Object.prototype.toString 方法在没有被重写的情况下,能够返回一个表示对象类型的标准字符串格式,即 [object Type],其中 Type 是对象的内部类型名称。这对于准确识别对象类型非常有用。
  3. 使用 call 方法

    • call 方法属于 Function.prototype,它允许你改变函数调用的上下文(即 this 值),并立即调用该函数。在这里,call(this) 使得 Object.prototype.toString 在当前上下文(this)中执行,从而获取该上下文的类型信息。

面试官:请你谈谈JS中几种常见的类型判断方法

用途

  • 类型检测

    • 通过 Object.prototype.toString.call(this),可以准确检测 this 指向的对象的类型,包括但不限于 "object""array""function""date""regexp" 等。这对于编写兼容性强、精度高的类型检查代码非常有用,尤其是在 typeof 无法提供足够信息时(例如,typeof [] 返回 "object" 而不是 "array")。

本篇文章就到此为止啦,希望通过这篇文章能对你了解JavaScript类型检测有所帮助,本人水平有限难免会有纰漏,欢迎大家指正。如觉得这篇文章对你有帮助的话,欢迎点赞收藏加关注,感谢支持🌹🌹。

面试官:请你谈谈JS中几种常见的类型判断方法

转载自:https://juejin.cn/post/7371000326131171378
评论
请登录