当前位置:网站首页>The four methods of judging JS data type
The four methods of judging JS data type
2022-08-01 11:21:00 【little snail game】
在 ECMAScript 规范中,共定义了 7 种数据类型,分为 基本类型 和 引用类型 两大类,如下所示:
基本类型:String、Number、Boolean、Symbol、Undefined、Null
引用类型:Object
基本类型也称为简单类型,由于其占据空间固定,是简单的数据段,为了便于提升变量查询速度,将其存储在栈中,即按值访问.
引用类型也称为复杂类型,由于其值的大小会改变,所以不能将其存放在栈中,否则会降低变量查询速度,因此,其值存储在堆(heap)中,而存储在变量处的值,是一个指针,指向存储对象的内存处,即按址访问.引用类型除 Object 外,还包括 Function 、Array、RegExp、Date 等等.
鉴于 ECMAScript 是松散类型的,因此需要有一种手段来检测给定变量的数据类型.对于这个问题,JavaScript 也提供了多种方法,但遗憾的是,不同的方法得到的结果参差不齐.
下面介绍常用的4种方法,并对各个方法存在的问题进行简单的分析.
1、typeof
typeof 是一个操作符,其右侧跟一个一元表达式,并返回这个表达式的数据类型.返回的结果用该类型的字符串(全小写字母)形式表示,包括以下 7 种:number、boolean、symbol、string、object、undefined、function 等.
1 2 3 4 5 6 7 8 9 10 |
|
有些时候,typeof 操作符会返回一些令人迷惑但技术上却正确的值:
- 对于基本类型,除 null 以外,均可以返回正确的结果.
- 对于引用类型,除 function 以外,一律返回 object 类型.
- 对于 null ,返回 object 类型.
- 对于 function 返回 function 类型.
其中,null 有属于自己的数据类型 Null , 引用类型中的 数组、日期、正则 也都有属于自己的具体类型,而 typeof 对于这些类型的处理,只返回了处于其原型链最顶端的 Object 类型,没有错,但不是我们想要的结果.
2、instanceof
instanceof 是用来判断 A 是否为 B 的实例,表达式为:A instanceof B,如果 A 是 B 的实例,则返回 true,否则返回 false. 在这里需要特别注意的是:instanceof 检测的是原型,我们用一段伪代码来模拟其内部执行过程:
1 2 3 4 5 6 7 8 9 |
|
从上述过程可以看出,当 A 的 __proto__ 指向 B 的 prototype 时,就认为 A 就是 B 的实例,我们再来看几个例子:
1 2 3 4 5 6 7 8 9 10 |
|
我们发现,虽然 instanceof 能够判断出 [ ] 是Array的实例,但它认为 [ ] 也是Object的实例,为什么呢?
我们来分析一下 [ ]、Array、Object 三者之间的关系:
从 instanceof 能够判断出 [ ].__proto__ 指向 Array.prototype,而 Array.prototype.__proto__ 又指向了Object.prototype,最终 Object.prototype.__proto__ 指向了null,标志着原型链的结束.因此,[]、Array、Object 就在内部形成了一条原型链:

从原型链可以看出,[] 的 __proto__ 直接指向Array.prototype,间接指向 Object.prototype,所以按照 instanceof 的判断规则,[] 就是Object的实例.依次类推,类似的 new Date()、new Person() 也会形成一条对应的原型链 .因此,instanceof 只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型.
instanceof 操作符的问题在于,它假定只有一个全局执行环境.如果网页中包含多个框架,那实际上就存在两个以上不同的全局执行环境,从而存在两个以上不同版本的构造函数.如果你从一个框架向另一个框架传入一个数组,那么传入的数组与在第二个框架中原生创建的数组分别具有各自不同的构造函数.
1 2 3 4 5 |
|
针对数组的这个问题,ES5 提供了 Array.isArray() 方法 .该方法用以确认某个对象本身是否为 Array 类型,而不区分该对象在哪个环境中创建.
1 2 3 |
|
Array.isArray() 本质上检测的是对象的 [[Class]] 值,[[Class]] 是对象的一个内部属性,里面包含了对象的类型信息,其格式为 [object Xxx] ,Xxx 就是对应的具体类型 .对于数组而言,[[Class]] 的值就是 [object Array] .
3、constructor
当一个函数 F被定义时,JS引擎会为F添加 prototype 原型,然后再在 prototype上添加一个 constructor 属性,并让其指向 F 的引用.如下所示:

当执行 var f = new F() 时,F 被当成了构造函数,f 是F的实例对象,此时 F 原型上的 constructor 传递到了 f 上,因此 f.constructor == F

可以看出,F 利用原型对象上的 constructor 引用了自身,当 F 作为构造函数来创建对象时,原型上的 constructor 就被遗传到了新创建的对象上, 从原型链角度讲,构造函数 F 就是新对象的类型.这样做的意义是,让新对象在诞生以后,就具有可追溯的数据类型.
同样,JavaScript 中的内置对象在内部构建时也是这样做的:

细节问题:
1. null 和 undefined 是无效的对象,因此是不会有 constructor 存在的,这两种类型的数据需要通过其他方式来判断.
2. 函数的 constructor 是不稳定的,这个主要体现在自定义对象上,当开发者重写 prototype 后,原有的 constructor 引用会丢失,constructor 会默认为 Object

为什么变成了 Object?
因为 prototype 被重新赋值的是一个 { }, { } 是 new Object() 的字面量,因此 new Object() 会将 Object 原型上的 constructor 传递给 { },也就是 Object 本身.
因此,为了规范开发,在重写对象原型时一般都需要重新给 constructor 赋值,以保证对象实例的类型不被篡改.
4、toString
toString() 是 Object 的原型方法,调用该方法,默认返回当前对象的 [[Class]] .这是一个内部属性,其格式为 [object Xxx] ,其中 Xxx 就是对象的类型.
对于 Object 对象,直接调用 toString() 就能返回 [object Object] .而对于其他对象,则需要通过 call / apply 来调用才能返回正确的类型信息.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
边栏推荐
- Basic configuration commands of cisco switches (what is the save command of Huawei switches)
- JWT
- 【CLion】CLion 总是提示 “This file does not belong to any project target xxx” 的解决方法
- retired paddling
- 冰冰学习笔记:gcc、gdb等工具的使用
- A new generation of ultra-safe cellular batteries, Sihao Airun goes on sale starting at 139,900 yuan
- PDMan-domestic free general database modeling tool (minimalist, beautiful)
- 新书上市 |《谁在掷骰子?》在“不确定性时代”中确定前行
- 【cartographer ros】十: 延时和误差分析
- Pve delete virtual machine "for a collection"
猜你喜欢

复现assert和eval成功连接或失败连接蚁剑的原因

一文说明白ECDSA spec256k1 spec256r1 EdDSA ed25519千丝万缕的关系

新一代超安全蜂窝电池, 思皓爱跑上市13.99万元起售

Golang内存分析工具gctrace和pprof实战

重庆市大力实施智能建造,推动建筑业数字化转型,助力“建造强市”

Mysql索引相关的知识复盘一

【likeshop】回收租凭系统100%开源无加密 商城+回收+租赁

Solve vscode input! Unable to quickly generate skeletons (three methods for the new version of vscode to quickly generate skeletons)

.NET深入解析LINQ框架(三:LINQ优雅的前奏)

Promise learning (1) What is Promise?how to use?How to solve callback hell?
随机推荐
.NET性能优化-使用SourceGenerator-Logger记录日志
Promise to learn several key questions (3) the Promise - state change, execution sequence and mechanism, multitasking series, abnormal penetration, interrupt the chain of Promise
Online - GCeasy GC log analysis tools
Qt 支持HEIC/HEIF格式图片
Cross-domain network resource file download
用户体验 | 如何度量用户体验 ?
稀疏表示--学习笔记
重庆市大力实施智能建造,推动建筑业数字化转型,助力“建造强市”
通配符SSL证书不支持多域名吗?
【cartographer ros】十: 延时和误差分析
leetcode/submatrix element sum
华硕和微星多款产品将升级英特尔Arc A380和A310显卡
Promise学习(三)Promise的几个关键性问题 -- 状态改变、执行顺序与机制、多任务串联、异常穿透、中断promise链
石头科技打造硬核品牌力 持续出海拓展全球市场
解决vscode输入! 无法快捷生成骨架(新版vscode快速生成骨架的三种方法)
mysql进阶(二十二)MySQL错误之Incorrect string value中文字符输入错误问题分析
小程序毕设作品之微信美食菜谱小程序毕业设计成品(4)开题报告
For small applications, which database is better to use?
语音聊天app源码——语音聊天派对
Android Security and Protection Policy