数据类型检测: 怎么实现一个 instanceof ? 您所在的位置:网站首页 instanceof能否判断基本数据类型 数据类型检测: 怎么实现一个 instanceof ?

数据类型检测: 怎么实现一个 instanceof ?

2023-11-27 06:50| 来源: 网络整理| 查看: 265

趁着整理之前写的JavaScript基础笔记, 把数据类型的四种检测方式彻底整明白了, 我觉得面试能把这些答上应该是没什么问题了.

本文内容: 介绍了四种检测方式, 实现了instanceof, 一个完美的数据类型检测函数

数据类型检测中的四种方法 tyopeof [value]

typeof是执行效率最高的方法, 它在底层是根据数据在内存存储的二进制值来判断他的数据类型的, 也因为这样的特性导致了它没办法分清null和object

000:对象010:浮点数100:字符串110:布尔1:整数000: null(空指针)

由于对象的二进制值都是以000开头的, 而null因为全部位都为0,所以对象与null检测出来都为 “object”.

Function 作为一种特殊的对象, 有他自己的特殊的属性(实现了call方法), JavaScript设计者认为有必要区分object与function, 并无设计缺陷上的问题.

检测结果: “number / boolean / string / null / undefined / symbol / bigint / object”

还有一个需要注意到的点, 就是typeof检测返回的值是一个string类型, 所以嵌套的检测用于返回string类型

在C++底层提供了特殊检测方法, 他按照存储值去检测数据类型, 所以它检测速度快效率高,但是没办法检测细分的对象类型和null

[value] instanceof [constructor]

这个方法的本意是检测某个实例是否属于某一个类, 所以它没有办法检测原始值类型

检测原理:

如果构造函数上存在[Symbol.hasInstance] 方法,则返回该函数的执行结果.

如不存在, 则去[value].__proto__(原型链)上查找, 构造函数是否在[value]的原型链上

从检测原理可以看出, 这个方法有他明显的缺点:

[Symbol.hasInstance]可以改变instanceof 检测行为.

prototype属性是可以被重定向的, 所以可能导致结果不准确

那么, 怎么实现一个instanceof?

首先根据instanceof的检测原理, 我们可以得出instanceof的运行规律:

"右边的值有[Symbol.hasInstance] 方法吗?" 有 => 执行(行为1)

if (typeof rightVal[Symbol.hasInstance] === 'function') { return rightVal[Symbol.hasInstance](leftVal) }

"没有, 去左边的值的原型链上查找."(行为2)

let leftProto = Object.getPrototypeOf(leftVal) while (leftProto) { if (leftProto === rightVal.prototype) return true // 如果找不到, 就往左值的下一级原型找 leftProto = Object.getPrototypeOf(leftProto) } return false }

再加上一些检测参数的办法就完成拉 (▽)

function _instanceof(leftVal, rightVal) { let leftType = typeof leftVal, rightType = typeof rightVal, objTypeReg = /^(object|function)$/ if (leftType == null || rightType == null) return false if (!objTypeReg.test(leftType) || !objTypeReg.test(rightType)) return false //行为1 if (typeof rightVal[Symbol.hasInstance] === 'function') { return rightVal[Symbol.hasInstance](leftVal) } // 行为2 let leftProto = Object.getPrototypeOf(leftVal) while (leftProto) { if (leftProto === rightVal.prototype) return true // 如果找不到, 就往左值的下一级原型找 leftProto = Object.getPrototypeOf(leftProto) } return false } [value].constructor === [constructor]

这个方法本意是为了访问实例的构造函数, 但是构造函数的指向也是可以被改变的,所以也不太好

Objcet.prototype.toString.call([value])

这个方法除了名字长点, 可以说是数据类型检测的最优解, 因为他可以兼容检测所有的数据类型, 包括对象的细分类型.

原理: toString在正常情况下是用来字符化值的, 但是在顶级对象Object上的toString有一些不同, 它会去查找[value]上的[Symbol.toStringTag]属性, 如果存在则返回一个格式为: “[object ? ]” 的字符串.

名字长的解决方案:

let class2type = {} toString = {}.prototype.toString // 简写 一个完美的类型检测函数: function toType(obj) { // 原始值 if (typeof obj !== 'function' && typeof obj !== 'object') return typeof obj var instanceExp = /^\[object ([a-zA-Z]+)\]$/ var value = instanceExp.exec(toString.call(obj))[1] || 'object' return value.toLowerCase() } 感谢😘

如果觉得文章内容对你有帮助:

❤️欢迎关注点赞哦! 我会尽最大努力产出高质量的文章 个人公众号: 前端Link 联系作者: linkcyd 😁 往期:

JavaScript数据类型细节点: 用简单的方式让你理解概念


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有