JavaScript之类型检测

面试题

类型检测的方法有哪些,平时一般都是怎么使用的?

typeof null 的结果是什么,为什么?

typeof NaN 的结果是什么?

instanceof 操作符的实现原理及实现

今天,我们来讲一讲 JavaScriipt中关于类型检测相关的知识点,上面有几道比较流行的面试题,大家可以试着回答一下,看看自己的能力水平如何,如果所有的问题都能很好的回答出来,那么恭喜你,你是一个隐形的大佬,接下来的内容就可以直接跳过。

类型检测

比较常见的类型检测方法有如下几种:

  1. typeof
  2. instanceof
  3. Object.prototype.toString
  4. constructor

typeof

typeof 是日常开发中比较常用的类型检测方法,它是 JavaScript 中的保留字。typeof 运算符返回一个字符串,表示操作数的类型。下表总结了 typeof 运算符的返回值。

类型
Undefined 'undefined'
Null 'object'
Boolean 'boolean'
Number 'number'
BigInt 'bigint'
String 'string'
Symbol 'symbol'
Function 'function'
Object 'object'
Date 'object'
Array 'object'
Regexp 'object'

那么对于Number中三个特殊的数值执行 typeof 运算,其返回值是什么呢?

csharp 复制代码
typeof NaN
> "number"
typeof Infinity
> "number"
typeof -Infinity
> "number"

通过上述的内容,可知在这其中只有两个类型的值是不符合预期的,一个是Null(预期应该是'null'),另外一个是Function(预期应该是'object'),那具体原因是为什么呢?

typeof null

在JavaScript最初的实现中,JavaScript 中的值都是由一个表示类型的标签和实际数据值表示的。对象的类型标签是 0。由于 null 代表的是空指针(大多数平台下由机器码 NULL 指针表示,其值为 0x00),因此,null 的类型标签是 0,typeof null 也因此返回 'object'。

曾有一个 ECMAScript 的修复提案(通过选择性加入的方式),但被拒绝了,因为目前有很多程序代码是依靠 typeof null === 'object' 来实现逻辑的,因此这个缺陷将一直会保留,永远不会被修复。

csharp 复制代码
typeof null
> "object"
标签 类型
000 对象
1 整数
010 浮点数
100 字符串
110 布尔

typeof Function

这里贴一段ECMAScript规范的文档,其中明确的表明了 typeof 去检测引用类型的时候,会去看这个引用类型内部有没有 [[call]] 方法,如果有,则返回 function ;如果没有,则返回object

通过上面的分析可知,typeof 操作符适合对 基本类型 (除 null 之外)及 function 的检测使用,而对引用数据类型(如 Array)等不适合使用。

instanceof

instanceof 运算符 用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

instanceof 运算符左操作数为对象,不是就返回 false,右操作数必须为函数对象或者函数构造器,不是就返回TypeError。

typescript 复制代码
1 instanceof Number
> false
​
new Number(1) instanceof Number
> true
​
1 instanceof 3
> Uncaught TypeError: Right-hand side of 'instanceof' is not an object
    at <anonymous>:1:3

instanceof 适合用于判断对象是否属于 Array、Date 和 RegExp 等内置对象。

不同 window 或 iframe 之间的对象类型检测无法使用 instanceof 检测。

instanceof实现
javascript 复制代码
function myInstanceOf(left, right) {
    let proto = left.__proto__; // 实例对象的原型
    let prototype = right.prototype; // 构造函数的原型
    if (proto === null || prototype === null) {
        return false
    } else if (proto === prototype) {
        return true;
    } else {
        myInstance(proto, right) // 递归遍历原型链
    }
}

Object.prototype.toString

toString() 方法返回一个表示该对象的字符串 "[object Type]" ,这里的 Type 是对象的类型。

所有继承自 Object.prototype 的对象(即,除了 null-prototype 对象之外的对象)都继承 toString() 方法。当你创建一个自定义对象时,你可以重写 toString() 以调用自定义方法,以便将自定义对象转换为一个字符串。Object.prototype.toString 属于 Object 的原型方法,而 Array 或 Function 等类型作为 Object 的实例,都重写了 toString 方法。因此,不同对象类型调用 toString 方法时,调用的是重写后的 toString 方法,而非 Object 上原型 toString 方法,所以采用 xxx.toString() 不能得到其对象类型,只能将 xxx 转换成字符串类型,因此只有使用 Object.prototype.toString 方法才能精准地判断出值的数据类型。其各类型对应的返回值如下:

类型
Undefined "[object Undefined]"
Null "[object Null]"
Boolean "[object Boolean]"
Number "[object Number]"
BIgInt "[object BigInt]"
String "[object String]"
Symbol "[object Symbol]"
Function "[object Function]"
Object "[object Object]"
Daten "[object Date]"
Array "[object Array]"
Regexp "[object RegExp]"

改写toString

javascript 复制代码
class People {
    constructor(name) {
        this.name = name;
    }
}
const lilei = new People('lilei');
lilei.toString()
> "[object Object]"  // 未改写
​
class People {
    constructor(name) {
        this.name = name;
    }
    toString() {
        return this.name
    }
}
const lilei = new People('lilei');
lilei.toString()
> "lilei"  // 改写

Constructor

任何对象都有 constructor 属性,继承自原型对象,根据原型链之间的关系constructor 会指向构造这个对象的构造器或构造函数,因此可以通过constructor属性来判断对象的类型。

ini 复制代码
class People {
    constructor(name) {
        this.name = name;
    }
}
const lilei = new People('lilei');
lilei.constructor === People
> true

数组检测

ECMAScript5 将 Array.isArray() 正式引入 JavaScript,该方法能准确检测一个变量是否为数组类型。

ini 复制代码
Array.isArray(variable);

答案

问1:类型检测的方法有哪些,平时一般都是怎么使用的?

javascript 复制代码
答:类型检测一般有 typeof、instanceof、Object.protorype.toString以及Constructor。其中 typeof常用于
基本数据类型(除null)和 Function 的检测使用,instanceof 常用于引用类型的使用,其中数组可以使用 
ECMAScript5 中新引入的 `Array.isArray()` 来检测,而Object.protorype.toString 和 Constructor 可以适
用于所有的类型检测。

问2:typeof null 的结果是什么,为什么?

csharp 复制代码
答:结果为 object
因为在JavaScript最初的实现中,JavaScript 中的值都是由一个表示类型的标签和实际数据值表示的。对象的类型标
签是 0。由于 null 代表的是空指针(大多数平台下由机器码 NULL 指针表示,其值为 0x00),因此,null 的类型
标签是 0,typeof null 也因此返回 'object'。

问3:typeof NaN 的结果是什么?

javascript 复制代码
答:结果为 Number
因为全局属性 NaN 是一个表示非数字的值,所以其类型依然是Number。

问4:instanceof 操作符的实现原理及实现

javascript 复制代码
答: instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
实现:
function myInstanceof(left, right) {
    let proto = left.__proto__;
    let prototype = right.prototype;
    if(proto === null || prototype === null) {
        return false;
    } else if (protp === prototype) {
        return true;
    } else {
        myInstance(proto, right);
    }
}

参考:

[1] 262.ecma-international.org/#sec-typeof...

[2] developer.mozilla.org/zh-CN/docs/...

[3] 262.ecma-international.org/#sec-typeof...

[4] developer.mozilla.org/zh-CN/docs/...

[5] developer.mozilla.org/zh-CN/docs/...

[6] developer.mozilla.org/zh-CN/docs/...

相关推荐
李先静3 分钟前
AWTK-WEB 快速入门(1) - C 语言应用程序
c语言·开发语言·前端
MR·Feng12 分钟前
使用Electron将vue2项目打包为桌面exe安装包
前端·javascript·electron
萧大侠jdeps24 分钟前
图片生成视频-右进
前端·javascript·音视频
Domain-zhuo1 小时前
JS对于数组去重都有哪些方法?
开发语言·前端·javascript
明月清风徐徐1 小时前
Vue实训---2-路由搭建
前端·javascript·vue.js
王解1 小时前
速度革命:esbuild如何改变前端构建游戏 (1)
前端·vite·esbuild
葡萄城技术团队2 小时前
使用 前端技术 创建 QR 码生成器 API1
前端
DN金猿2 小时前
Vue移动端网页(H5)预览pdf文件(pdfh5和vue-pdf)(很详细)
前端·vue.js·pdf
鸽鸽程序猿2 小时前
【前端】javaScript
开发语言·前端·javascript
秦时明月之君临天下2 小时前
React和Next.js的相关内容
前端·javascript·react.js