持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情
在学习JavaScript过程中数据类型是必不可少的一环,今天我们来看看JavaScript中有哪些数据类型吧。
ECMAScript语言类型
ECMAScript语言类型是分为Undefined、Null、Boolean、String、Number、Symbol、BigInt 和 Object
的,也就是我们常说的值类型和引用类型。
Undefined 类型
Undefined 类型只有一个值就是undefined
,一些变量没有被赋值,那么他就是undefined
Null类型
Null 类型只有一个值就是null
。
Undefined和Null的区别?
undefined
表示未定义,我们声明了一个变量但没给他赋值,或者访问了一个不存在的属性;null
表示他是一个空值(空值也是有值)。undefined
是一个全局的属性,可以对他赋值,但是被不会修改,因为他是不可配置的,null
是一个关键字,不能被赋值。
Boolean类型
Boolean
类型表示有两个值的逻辑实体true、false
String类型
JavaScript中的字符串类型表示文本数据,它包含0个或多个16位无符号整数值的的“元素”,在字符串中的每个元素占据了字符串的位置。第一个元素的索引为 0
,下一个是索引 1
,依此类推。字符串的长度是它的元素的数量。
StringIndexof
StringIndexof(string, serachValue, fromIndex)
接受三个参数,用来查找字符串中是否有指定的字符,没有就返回-1,具体步骤如下:
- 将
string
断言成字符串,如果不是字符串类型就会直接报错 serachValue
会被转换成字符串fromIndex
接受一个非负整数,否则会对其进行转换,能被转成数字的转成数字('1' => 1),否则都是0,负数也是0(或者是被忽略掉,只有转换后是非负整数才会生效)- 定义一个变量len,他是字符串string的长度
- 判断
serachValue
是不是空字符串,并且fromIndex ≤ len
,那么就返回fromIndex
- 定义一个变量
searchLen
其长度为serachValue
的长度 - 定义一个变量i,从
fromIndex
开始,到i ≤ len-searchLen
结束,每次遍历i + searchLen
长度的字符串,找到了就返回i - 没找到返回-1
Symbol类型
符号(Symbols)类型是唯一且不可修改的原始值,并且可以用来作为对象的键(key)
Number类型
Number类型和BigInt类型都是数字类型。数字类型是一种以IEE754为标准的双精度64位二进制格式的值,从 -(2^53 -1)
到 2^53 - 1
之间的数字,还有+0、-0、NaN、+Infinity、-Infinity
。
要检查值是否大于或小于 ±Infinity
,你可以使用常量 Number.MAX_VALUE
和 Number.MIN_VALUE
。
从 ECMAScript 2015 开始,除了
Number.MAX_SAFE_INTEGER
和Number.MIN_SAFE_INTEGER
,你还可以通过Number.isSafeInteger()
来检查值是否在双精度浮点数的取值范围内。
超出这个范围,JavaScript 中的整数将不再安全,该值将表示为与该值近似的双精度浮点数。
BigInt类型
可以表示任意精度的整数。使用 BigInt,您可以安全地存储和操作大整数,甚至可以超过数字类型的安全整数限制。
BigInt 是通过在整数末尾附加字母 n
或调用构造函数来创建的。
BigInt
不能与数字相互运算。否则,将抛出 TypeError
。
如何判断数据类型
typeof 操作符
typeof 操作符是一个一元运算符,返回一个字符串,表示未经计算的操作数的类型。他可以判断基础数据类型,对于引用类型都是object
,不能准确判断,其中有两个特例,对于null
会被判断为object
,函数类型可以被准确判断出来是funciton
数据类型 | 结果 |
Undefined | "undefined" |
Boolean | "boolean" |
Number | "number" |
String | "string" |
Symbol | "symbol" |
BigInt | "bigint" |
Null | "object' |
Function | "funciton" |
Object | "object" |
其他引用类型 | "object" |
那么为什么
null
会被判断为object
呢? 答:不同的对象在底层都表示为二进制, 在 JavaScript 中二进制前三位都为 0 的话会被判断为 object 类型, null 的二进制表示是全 0, 自然前三位也是 0, 所以执行 typeof 时会返回“object”。
instanceof
instanceof
运算符用于检测构造函数的 prototype
属性是否出现在某个实例对象的原型链上。
// object为实例对象,constructor为构造函数
object instanceof constructor
instanceof
可以判断引用数据类型,但判断不了基本数据类型,只能判断基本数据类型的包装类型。
function instanceOf(proto, Ctor) {
if ((typeof proto !== 'object' || proto === null) && typeof proto !== 'function') return false;
let leftProto = Object.getPrototypeOf(proto);
const rightProto = Ctor.prototype;
while (leftProto) {
if (leftProto === rightProto) return true;
leftProto = Object.getPrototypeOf(leftProto);
}
return false
}
Object.prototype.toString()
Object.prototype.toString
方法也是可以用来判断数据类型的,他会返回一个字符串"[object Class]"
,Class
类似该数据类型的构造函数。他可以准确地判断出给个数据类型。简单举例如下:
Object.prototype.toString.call({}) // "[object Object]"
Object.prototype.toString.call([]) // "[object Array]"
Object.prototype.toString.call(1) // "[object Number]"
Object.prototype.toString.call('1') // "[object String]"
Object.prototype.toString.call(true) // "[object Boolean]"
// ...
三种区别
方法 | 基本数据类型 | 引用数据类型 | 注意 |
typeof | ✅ | ❌ | NaN... |
instanceof | ❌ | ✅ | 多窗口、右操作数必须是函数或class |
toString | ✅ | ✅ | 小心内置原型 |
isPrototypeOf | ❌ | ✅ | 小心null和undefined |
等比较 | ✅ | ✅ | 特殊对象 |
instanceof和isPrototypeOf有什么不同?
isPrototypeOf()
方法用于测试一个对象是否存在于另一个对象的原型链上prototypeObj.isPrototypeOf(object)
instanceof
运算符用于检测构造函数的prototype
属性是否出现在某个实例对象的原型链上
实现一个判断常见数据类型判断的方法
/**
* 数据类型判断通用方法
*/
const getType = (obj) => {
if (obj == null) return obj + '';
return (typeof obj === 'object' || typeof obj === 'funciton')
? (Object.prototype.toString.call(obj).toLocaleLowerCase().slice(8, -1) || 'object')
: typeof obj;
}
数据类型转换
ECMAScript语言会根据需要进行隐式的类型转换,而BigInt没有隐式转换,必须显示的调用他来转换成其他类型。
ToPrimitive ( input [ , preferredType ] )
将输入的参数转换成非对象类型(原始值)
-
断言:input输入是一个ECMAScript语言的值
-
如果输入的类型是对象
-
获取对象上toPrimitive方法,如果存在,
- 如果preferredType不存在,按default转换
- 如果preferredType是“string”,那就按“string”转换
- 否则,将断言preferredType成“number“,按“number“转换
- 如果经过转换后result不是对象了就返回,否则报错
Throw a TypeError exception
-
-
返回input(原始类型)
对象转原始值OrdinaryToPrimitive ( O, hint )
-
将O断言成对象类型
-
判断要转换的类型
hint
是string还是number -
如果要转换成string,那么调用顺序是"toString","valueOf"
- 如果调用toString返回一个原始值,JavaScript 将这个值转换为字符串,并返回这个字符串结果。
- 如果对象没有 toString 方法,或者这个方法并不返回一个原始值,那么 JavaScript 会调用 valueOf 方法。如果存在这个方法,则 JavaScript 调用它。如果返回值是原始值,JavaScript 将这个值转换为字符串,并返回这个字符串的结果
- 否则,JavaScript 无法从 toString 或者 valueOf 获得一个原始值,这时它将抛出一个类型错误异常
-
如果要转换成number,那么调用顺序是"valueOf","toString"
- 同3
-
否则,JavaScript 抛出一个类型错误异常
ToBoolean ( argument )
argument Type | result |
Undefined | false |
Null | false |
Boolean | return argument |
Number | if +0、-0、NaN return false; otherwise return true |
String | 空字符串返回false,其他的都是true |
Symbol | true |
BigInt | If argument is 0ℤ, return false; otherwise return true. |
Object | true |
ToNumber
argument Type | result |
Undefined | NaN |
Null | +0 |
Boolean | true: 1; false: 0 |
Number | Return argument (no conversion). |
String | 见例子 |
Symbol | TypeError |
BigInt | TypeError |
Object | 1. Let primValue be ? ToPrimitive(argument, number). 2. Return ? ToNumber(primValue). |
console.log(Number()) // +0
console.log(Number(undefined)) // NaN
console.log(Number(null)) // +0
console.log(Number(false)) // +0
console.log(Number(true)) // 1
console.log(Number("123")) // 123
console.log(Number("-123")) // -123
console.log(Number("1.2")) // 1.2
console.log(Number("000123")) // 123
console.log(Number("-000123")) // -123
console.log(Number("0x11")) // 17
console.log(Number("")) // 0
console.log(Number(" ")) // 0
console.log(Number("123 123")) // NaN
console.log(Number("foo")) // NaN
console.log(Number("100a")) // NaN
Number
函数会尽可能多的解析数值字符,将它转换成整数或浮点数,忽略所有前导的0,如果有一个字符不是数字,结果都会返回 NaN。除此之外我们还有parseInt 和 parseFloat 进行数值转换。
parseInt 只解析整数,parseFloat 则可以解析整数和浮点数, 尽可能解析更多数值字符,并忽略后面的内容。如果第一个非空格字符是非法的数字直接量,将最终返回 NaN。
ToString
argument Type | result |
Undefined | “undefined” |
Null | “null” |
Boolean | “true”; “false” |
Number | Number.toString(argument) |
String | Return argument (no conversion). |
Symbol | TypeError |
BigInt | BigInt.toString(argument) |
Object | 1. Let primValue be ? ToPrimitive(argument, number). 2. Return ? ToString(primValue). |
ToObject
始值通过调用 String()、Number() 或者 Boolean() 构造函数,转换为它们各自的包装对象。
null 和 undefined 属于例外,当将它们用在期望是一个对象的地方都会造成一个类型错误 (TypeError) 异常,而不会执行正常的转换。
JSON.stringify
运算符
在js运算中通常某些运算符会发生隐式类型转换,如一元操作符+、二元操作符+、==运算符
这些,在运算过程中会发生数据类型转换,得到的值和我们想象的可能不太一样
一元操作符+
当 + 运算符作为一元操作符的时候,查看 ES5规范1.4.6,会调用 ToNumber
处理该值,相当于 Number('1')
,最终结果返回数字。
转换步骤见上面ToNumber
函数
二元操作符+
- 如果操作数是对象,那么对象转为原始值
- 如果一个操作数是字符串,那么另一个操作数也转成字符串,进行字符串拼接
- 否则两个数都变成数字或NaN进行加法操作
==运算符
执行x == y
时
-
如果x和y是同一类型,执行===严格相等比较
-
x是null并且y是undefined,返回true
-
x是undefined并且y是null,返回true
-
如果x是Number,y是String,那么比较 x == ToNumber(y)
-
如果x是String,y是Number,那么比较 ToNumber(x) = y
-
如果x是BigInt,y是String
- 将string转换成Bigint,赋值与变量n
- n如果是NaN,返回false
- 返回x==n的结果
-
其中一个是Boolean,那么比较ToNumber(x) = y或x = ToNumber(y)
-
x是字符串或者数字,y是对象,判断x == ToPrimitive(y)
-
返回false
===严格相等比较
- 两者类型不同,返回false
- 如果x是数字类型或者BigInt,比较x是否等于y
- 返回SameValueNonNumeric(x, y)
SameValueNonNumeric(x, y)
-
x和y都不是Number或BigInt(不然在上述第二步就执行了)
-
x和y的类型是相同的(不然在上述第一步就执行了)
-
如果x是undefined,返回true
-
如果x是null,返回true
-
如果x是string
- 只有x和y是完全相同的代码序列(长度相同、在相同的索引出有相同的代码单元)才返回true,否则返回false
-
如果x是boolean
- 只有x和y都是true或者false才返回true,否则返回false
-
如果x是symbol
- 只有x和y有相同的symbol值,才返回true,否则返回false
-
只有x和y有相同的对象值,才返回true,否则返回false