JS基础篇:4、数据类型与类型转换

436 阅读6分钟

JS数据类型

ES6 前,JavaScript 共有六种数据类型:Undefined、Null、Boolean、Number、String、Object

ES6 中新增了一种 Symbol 。这种类型的对象永不相等,即始创建的时候传入相同的值,可以解决属性名冲突的问题,做为标记。

基本数据类型和引用数据类型

基本类型:是除 ObjectUndefined、Null、Boolean、Number、String、Symbol

特点:
1. 基本类型的访问是按值访问的;
2. 不能添加属性和方法;
3. 基本类型的变量存在放栈区,包括变量标识符和变量的值(栈区不会太大,主要用来存在基本类型);
4. 基本类型的复制是在栈内存中开辟一个新的存储来存储新的变量;

引用类型:主要分为三类

  1. 基本引用类型:Object Date、Function、Array、RegExp;

  2. 基本包装类型:String、Number、Boolean;

  3. 单体内置对象: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"会变成1,"123"会变成123,而"01"会变成1(前导的零被忽略了);
  2.    如果字符串中包含有效的浮点格式,如"1.1",则将其转换为对应的浮点数值(同样,也会忽略前导零);
  3.   如果字符串中包含有效的十六进制格式,例如"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]"