在ES6之前,JavaScript中有6种数据类型,其中5种简单数据类型(也称基本数据类型):Undefined Null Boolean Number String;和一种复杂数据类型(也称引用数据类型):Object。而在ES6中,又新增了一种简单数据类型:symbol。
以下是JavaScript高级程序设计(第三版),就是俗称的小红书中对数据类型的定义:
下面我们就来看看在JS中的数据类型究竟是长什么样的?
ES6之前的数据类型
如上所说:ES6之前JavaScript中有6种数据类型:数字(number)、字符串(string)、布尔值(boolean)、undefined、null、对象(Object)。
简单数据类型
Undefined
全局属性undefined表示原始值undefined。它是一个JavaScript的 原始数据类型 。
undefined是全局对象的一个属性。也就是说,它是全局作用域的一个变量。undefined的最初值就是原始数据类型undefined。
一个没有被赋值的变量的类型是undefined。如果方法或者是语句中操作的变量没有被赋值,则会返回undefined。
一个函数如果没有使用return语句指定返回值,就会返回一个undefined值。
Null
值 null 特指对象的值未设置。它是 JavaScript 基本类型 之一,在布尔运算中被认为是falsy。
值 null 是一个字面量,不像 undefined,它不是全局对象的一个属性。null 是表示缺少的标识,指示变量未指向任何对象。把 null 作为尚未创建的对象,也许更好理解。在 API 中,null 常在返回类型应是一个对象,但没有关联的值的地方使用。
null 与 undefined 的不同点:当检测 null 或 undefined 时,注意相等(==)与全等(===)两个操作符的区别 ,前者会执行类型转换
1 | typeof null // "object" (因为一些以前的原因而不是'null') |
Boolean
布尔表示一个逻辑实体,可以有两个值:true 和 false。
Number
根据 ECMAScript 标准,JavaScript 中只有一种数字类型:基于 IEEE 754 标准的双精度 64 位二进制格式的值(-(253 -1) 到 253 -1)。它并没有为整数给出一种特定的类型。除了能够表示浮点数外,还有一些带符号的值:+Infinity,-Infinity 和 NaN (非数值,Not-a-Number)。
String
JavaScript的字符串类型用于表示文本数据。它是一组16位的无符号整数值的“元素”。在字符串中的每个元素占据了字符串的位置。第一个元素的索引为0,下一个是索引1,依此类推。字符串的长度是它的元素的数量。
不同于类 C 语言,JavaScript 字符串是不可更改的。这意味着字符串一旦被创建,就不能被修改。但是,可以基于对原始字符串的操作来创建新的字符串。
复杂数据类型
Object
对象类型包括:数组(Array)、函数(Function)、还有两个特殊的对象:正则(RegExp)和日期(Date)。
判断数据类型的方法
先放一张图
1.typeof
typeof返回一个表示数据类型的字符串,返回结果包括:number、string、boolean、object、undefined、function。
语法
typeof 运算符后接操作数:
- typeof operand
- typeof(operand)
详细用法可以参考MDN
typeof可以对基本类型number、string 、boolean、undefined做出准确的判断(null除外,typeof null===“object”,这是由于历史的原因,我就不巴拉巴拉了,其实我也说不清楚😢);而对于引用类型,除了function之外返回的都是object。但当我们需要知道某个对象的具体类型时,typeof就显得有些力不从心了。
2.instanceof
当我们需要知道某个对象的具体类型时,可以用运算符 instanceof,instanceof操作符判断左操作数对象的原型链上是否有右边这个构造函数的prototype属性,也就是说指定对象是否是某个构造函数的实例,最后返回布尔值。其原理如下:
1 | 模拟instanceof的内部实现过程: |
从上述过程可以看出,当 A 的 __proto__
指向 B 的 prototype
时,就认为A就是B的实例,我们再来看几个例子:
1 | [] instanceof Array; //true |
我们发现,虽然 instanceof 能够判断出 [] 是Array的实例,但它认为 [] 也是Object的实例,为什么
从原型链可以看出,[] 的 proto 直接指向Array.prototype, 间接指向Object.prototype, 所以按照 instanceof 的判断规则,[] 就是Object的实例。
【注意】:instanceof运算符只能用于对象,不适用原始类型的值。
3.constructor
constructor属性的作用是,可以得知某个实例对象,到底是哪一个构造函数产生的。
例如:
1 | var f = new F(); |
但是 constructor 属性易变,不可信赖,这个主要体现在自定义对象上,当开发者重写prototype后,原有的constructor会丢失。
1 | function F() {} |
因此,为了规范,在重写对象原型时一般都需要重新给constructor赋值,以保证实例对象的类型不被改写。
1 | function F() {} |
小结:
- typeof可以准确地判断出基本类型,但是对于引用类型除function之外返回的都是object;
- 已知是引用类型的情况可以选用instanceof或constructor方法进行具体类型的判断:
- instanceof是基于原型链的;
- constructor 属性易变,不可信赖,为了规范,在重写对象原型时一般都需要重新给constructor赋值,以保证实例对象的类型不被改写;
ES6新增的Symbol(符号类型)
符号(Symbols)是ECMAScript 第6版新定义的。符号类型是唯一的并且是不可修改的, 并且也可以用来作为Object的key的值. 在某些语言当中也有类似的原子类型(Atoms). 你也可以认为为它们是C里面的枚举类型.
symbol 是一种基本数据类型 (primitive data type)。Symbol()函数会返回symbol类型的值,该类型具有静态属性和静态方法。它的静态属性会暴露几个内建的成员对象;它的静态方法会暴露全局的symbol注册,且类似于内建对象类,但作为构造函数来说它并不完整,因为它不支持语法:”new Symbol()”。
每个从Symbol()返回的symbol值都是唯一的。一个symbol值能作为对象属性的标识符;这是该数据类型仅有的目的。
BigInt
呃呃,不过好像前段时间又提出了一种新的基本数据类型:BigInt。
BigInt数据类型的目的是比Number数据类型支持的范围更大的整数值。在对大整数执行数学运算时,以任意精度表示整数的能力尤为重要。使用BigInt,整数溢出将不再是问题。
BigInt目前是第3阶段提案, 一旦添加到规范中,它就是JS 第二个数字数据类型,也将是 JS 第8种基本数据类型。