数据类型
js 共有八种数据类型,除了 object 为复杂数据类型(细分类型有 Array/Function/Set/Map/...),其余七种都是基本数据类型,没有挂载属性和方法。基本数据存储于栈空间;复杂数据存储于堆空间,将地址存储于栈空间
分类
围绕原始数据类型创建一个显式包装器对象从 ECMAScript 6 开始不再被支持。 然而,现有的原始包装器对象,如 new Boolean、new String 以及 new Number,因为遗留原因仍可被创建
Q&A
为什么
typeof null === 'object'
?
不同的对象在底层都表示为二进制,js 早期实现版本中,如果二进制前三位为 000 的话会被判断为 'object',null 的二进制表示全为 0,自然前三位也是 0,所以执行 typeof 时会返回 'object'
Number(a)
和new Number(a)
的区别
Number(a)
会将 a 转换为 number 数据new Number(a)
会创建一个对应 Number 类型的包装对象。包装对象有Number、String、Boolean
详见 https://www.cnblogs.com/thinking-better/p/5330120.html
为什么部分原始类型能调用方法,比如
'test'.length
js 执行到'test'.length
时,会将 'test'
转化为 new String('test')
,详见 http://es5.github.io/#x10.4.3
不过 2.toString()
会报错,原因是执行语句的时候会优先将点操作符解析为浮点数字面值的一部分,可以换成 2..toString()
/2 .toString()
/(2).toString()
null
和undefined
的区别
详见 https://www.ruanyifeng.com/blog/2014/03/undefined-vs-null.html
类型检测
typeof
。检测部分原始数据类型(number、string、boolean、symbol、undefined、bigint)和 function,其余返回 'object'instanceOf
。检测派生类型,原理是通过原型链判断。有以下缺点- 无法跨
iframe
工作 - 不能正确判断
Array.prototype
{ __proto__: Array.prototype } instanceof Array // true
- 无法跨
Object.prototype.toString.call
。通过 [[Class]] 类属性判断,但无法区分自定义对象类型;并且是装箱操作,会产生临时对象
一些特殊的情况如下:
typeof null; // "object"
typeof BigInt(1); // "bigint"
typeof undefined; // "undefined"
null === undefined; // false
null == undefined; // true
isNaN(1 + null); // false
isNaN(1 + undefined); // true
Q&A
怎么判断数组?
Array.isArray()
Object.prototype.toString.call
instanceof
(不建议)
怎么判断 plain object?
plain object 指的是通过字面量形式或者 new Object() 形式定义的对象,可以通过以下方式判断
function isPlainObject(obj) {
if (typeof obj !== "object" || obj === null) {
return false;
}
let temp = obj;
while (Object.getPrototypeOf(temp) !== null) {
temp = Object.getPrototypeOf(temp);
}
return Object.getPrototypeOf(obj) === temp;
}
instanceof 能否判断基本数据类型?
可以,通过重定义 intanceof 方法实现
数据转换
显式转换
- toNumber:
Number
、parseInt
、parseFloat
- toString:
String
、toString
- toBoolean:
Boolean
、!!
、!
、||
、&&
隐式转换
==
- 两两复杂数据类型对比,会比较地址是否一致
- 复杂数据类型和基础类型对比,复杂数据类型要转换为 string,依次调用 valueOf、toString,如果对比的基础数据类型是 number 或 boolean,还需要转换为 number 对比
- toNumber。
+[string]
- toString。
''+[number]
数据比较
==
===
Object.is
。对比严格相等,会处理一些特殊情况,比如 NaN、-0 和+0 不再相等...