JS数据类型
ES6 前,JavaScript 共有六种数据类型:Undefined、Null、Boolean、Number、String、Object。
ES6 中新增了一种 Symbol 。这种类型的对象永不相等,即始创建的时候传入相同的值,可以解决属性名冲突的问题,做为标记。
基本数据类型和引用数据类型
基本类型:是除 Object 的Undefined、Null、Boolean、Number、String、Symbol
特点:
1. 基本类型的访问是按值访问的;
2. 不能添加属性和方法;
3. 基本类型的变量存在放栈区,包括变量标识符和变量的值(栈区不会太大,主要用来存在基本类型);
4. 基本类型的复制是在栈内存中开辟一个新的存储来存储新的变量;
引用类型:主要分为三类
-
基本引用类型:Object Date、Function、Array、RegExp;
-
基本包装类型:String、Number、Boolean;
-
单体内置对象:Global、Math。
特点: 1. 引用类型的值是按引用访问的; 2. 引用类型可以拥有属性和方法,且可动态改变; 3. 存储需要内存的栈区和堆区,其中栈区保存变量标识符和指向内存中该对象的指针; 4. 引用类型的比较是引用的比较; 5. 引用类型的复制将复制引用地址。
-
Undefined 类型
在使用var/let 等声明变量但未对其加初始化时,这个变量就是undefined
var x;
console.log(x); // undefined
-
Null 类型
null是表示一个空对象指针,这也是typeof操作符检测 null 值时会返回 object 的原因。
console.log(typeof(null)); // object
-
null 和 undefined 的区别:
Null 只有一个值,是 null。不存在的对象。
Undefined 只有一个值,是undefined。没有初始化。undefined 是从 null 中派生出来的。
简单理解就是:undefined 是没有定义的,null 是定义了但是为空。
null和undefined没有toString()方法,用String函数不返回这两个值的字面量。
基本类型之间的转换
转数字 Number()
Number 函数将类型转换成数字类型,而且会忽略所有前导的 0,如果参数无法被转换为数字,则返回 NaN
NaN,即非数值,是一个特殊的Number值,NaN有两个特点:任何和NaN操作的结果都会返回NaN,NaN与任何值都不相等,包括NaN。使用isNaN()函数可以判断一个值是不是NaN,isNaN()在接收到一个参数时,会尝试将这个值转换为数值,任何不能转换为数值的值都会返回true
console.log(Number("x")) // NaN
console.log(Number(undefined)) // NaN
console.log(Number(null)) // +0
console.log(Number(false)) // +0
console.log(Number(true)) // 1
console.log(Number("1")) // 1
console.log(Number("-1")) // -1
console.log(Number("1.2")) // 1.2
console.log(Number("0123")) // 123
console.log(Number("-0123")) // -123
console.log(Number("")) // 0
console.log(Number({a: 1})) // NaN
console.log(Number([1, 2, 3])) // NaN
转字符串 String()
String 函数将类型转换成字符串类型
console.log(String()) // 空字符串
console.log(String(undefined)) // undefined
console.log(String(null)) // null
console.log(String(false)) // false
console.log(String(true)) // true
console.log(String(0)) // 0
console.log(String(-0)) // 0
console.log(String(NaN)) // NaN
console.log(String(1)) // 1
console.log(String({a: 1})) // "[object Object]"
console.log(String([1, 2, 3])) // "1,2,3"
转布尔值
Boolean 函数将类型转换成布尔类型,除了以下情况为false之外皆为true
Boolean(false) //false
Boolean(undefined) //false
Boolean(null) //false
Boolean(+0) //false
Boolean(-0) //false
Boolean(NaN) //false
Boolean("") //false
对象转字符串和数字
对象转字符串是通过toString方法,转数字的话是通过valueof方法。 所有的对象除了 null 和 undefined 之外的任何值都具有 toString 方法,通常情况下,它和使用 String 方法返回的结果一致。
Object.prototype.toString 方法会根据对象的[[class]]内部属性,返回[object class] 组成的字符串
console.log(({}).toString()) // "[object Object]"
console.log([].toString()) // ""
console.log([0].toString()) // 0
console.log([1, 2, 3].toString()) // 1,2,3
console.log((function(){}).toString()) // function (){}
console.log((/\d+/g).toString()) // /\d+/g
console.log((new Date(2021, 0, 1)).toString()) // Fri Jan 01 2021 00:00:00 GMT+0800
valueOf 主要把对象转换成一个基本数据的值
不同内置对象的 valueOf 实现:
- String => 返回字符串值
- Number => 返回数字值
- Date => 返回一个数字,即时间值
- Boolean => 返回 Boolean的自身值
- Object => 返回 this (自身)
console.log('123'.valueOf()) // '123'
console.log((1).valueOf()) // 1 如果是1.valueOf会报错 JS引擎无法确定这里的`.`是什么意思,是点运算符(对象方法)还是浮点数?
console.log(new Date().valueOf()) // 1628848676547
console.log(true.valueOf()) // true
console.log(({}).valueOf()) // {} {}.valueOf同样会报错 默认情况下{}会被浏览器解析成代码块 而不是对象 所以会报错
console.log([].valueOf()) // []
console.log((function(){}).valueOf()) // ƒ (){}
这时候有人会想那用Number方法转译对象呢?
console.log(Number(true)) // 1
console.log(Number(false)) // 0
console.log(Number(123)) // 123
console.log(Number(null)) // 0
console.log(Number(undefined)) // NaN
console.log(Number('0123')) // 123
console.log(Number('1.1')) // 1.1
console.log(Number('')) // 0
console.log(Number('0xa')) // 10
console.log(Number({})) // NaN
console.log(Number({a : 1})) // NaN
console.log(Number([])) // 0
console.log(Number([0])) // 0
console.log(Number([1, 2, 3])) // NaN
console.log(Number(function(){})) // NaN
console.log(Number(new Date(2021, 0, 1))) // 1609430400000
通过Number方法转译的结果我们得出以下结论
- 如果是 Boolean 值,true 和false 将分别被转换为1 和 0。
- 如果是数字值,只是简单的传入和返回。
- 如果是 null 值,返回0。
- 如果是 undefined,返回NaN。
- 如果是字符串,遵循下列规则:
- 如果字符串中只包含数字(包括前面带正号或负号的情况),则将其转换为十进制数值,即"1"会变成1,"123"会变成123,而"01"会变成1(前导的零被忽略了);
- 如果字符串中包含有效的浮点格式,如"1.1",则将其转换为对应的浮点数值(同样,也会忽略前导零);
- 如果字符串中包含有效的十六进制格式,例如"0xa",则将其转换为相同大小的十进制整数值;
- 如果字符串是空的(不包含任何字符),则将其转换为0;
- 如果字符串中包含除上述格式之外的字符,则将其转换为NaN。
- 如果是对象,则调用对象的valueOf()方法,然后依照前面的规则转换返回的值。如果转换的结果是NaN,则调用对象的toString()方法,然后再次依照前面的规则转换返回的字符串值。
JSON.stringify
JSON.stringify() 方法可以将一个 JavaScript 值转换为一个 JSON 字符串,实现上也是调用了 toString 方法,也算是一种类型转换的方法。 处理基本类型时,与使用toString基本相同,结果都是字符串,除了 undefined,在解析数组时表现不同
console.log(JSON.stringify(null)) // "null"
console.log(JSON.stringify(undefined)) // undefined,这个undefined不是字符串的undefined
console.log(JSON.stringify(true)) // "true"
console.log(JSON.stringify(42)) // "42"
console.log(JSON.stringify("42")) // "42"
console.log([1,2,3].toString()) // "1,2,3" 会给数组[]去掉
console.log(JSON.stringify([1,2,3])) // "[1,2,3]"