Javascript类型转换

321 阅读7分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情

在typescript还没出现之前,我相信不少伙伴对于javascript中的类型转换有点丈二和尚摸不着头脑,好比为啥'1' + 1 = '11'而1 + '1' = 2 ;那么今天我们就来好好梳理一下javascript这门语言中的类型转换,如果不是很明白javascript中有哪些类型,可以看看笔者之前写过的文章JS中令人疑惑的数据类型及其判断方法,相信看完对你学习本章内容有些许的帮助,那么,我们开始本章的学习吧。

原始类型转原始类型

原始值转布尔类型

首先布尔类型是怎么来的呢?是我们通过调用构造函数Boolean,new出一个实例对象,也就是说 new Boolean() 得到的 ,默认得到的是false,即 { Boolean : false },那我们看看原始值转成布尔类型会是什么?

  1. 字符串转布尔类型,只有空字符串即Boolean('')得到的是false,其他所有的字符串转布尔类型得到的都是true
  2. 数字类型转布尔类型Boolean(0)Boolean(NaN)这两个转成布尔值为false,其他都为true(通常我们不将NaN作为一种特殊的数据类型,而是作为数字类型的一种特殊的数据格式);
  3. 布尔值转布尔值,虽然听起来有点有病的味道,但是人家虽然无意义,但确实合法,即Boolean(false) 得到 falseBoolean(true) 得到true
  4. nullundefined 这两种类型转成布尔值都的得到 false

我们可以浅浅总结一下:原始值转布尔类型,有这五种情况得到的值为false,即空字符串数字0false本身null以及undefined,其他情况基本为true。

原始值转数字类型

数字类型也是调用构造函数Number, new 一个实例对象出来new Number() 得到的是数字0,那将原始值转成数字类型呢?

  1. 字符串类型转数字类型,只有字符串类型的数字转成数字类型可以转成对应的数字类型,其他非数字类型的字符串转成数字,只能得到NaN,即Number('123') --> 123 ; Number('abc') --> NaN
  2. 数字类型转数字类型,数字类型转数字类型得到的就是本身(合法但无意义);
  3. 布尔值转数字类型Number(true) --> 1,Number(false) --> 0;
  4. null转数字类型,Number(null) --> 0(特例需要记住);
  5. undefined转数字类型Number(undefined) --> NaN;

实际上Number这个构造函数内部是使用了ToNumber()方法使得其他类型的转化为数字类型的,但是javascript中,源码封装好的是我们不能使用ToNumber(),仅在Number这个构造函数内部调用。

原始值转字符串类型

既然boolean和字符串类型都是 new 他们构造函数的实例对象得到的,那我字符串是不是也可以呢? 当然可以字符串类型也可以看做 new String () 默认得到的是空字符串'',原始值转字符串类型呢?

  1. 字符串转字符串类型,字符串类型转字符串类型,得到字符串本身,String('abc') --> 'abc' ,(合法但无意义);
  2. 数字转字符串类型,数字类型转字符串得到字符串类型的数字,String(123) --> '123',String(Infinity) --> 'Infinity',String(NaN) --> 'NaN'
  3. 布尔值转字符串类型String(true) --> 'true'String(false) --> 'false'
  4. null转字符串类型String(null) --> 'null'
  5. null转字符串类型String(undefined) --> 'undefined'

原始值转对象

原始值转对象其实很简单,我们只需要理解一句话,那就是 new 一个构造函数得到的是实例对象,

let a = 'abc'
let b = new String(a);
console.log(typeof b);

对象转原始类型

image.png

image.png 同理数字类型和布尔值转对象一样是new 他们的构造函数,得到的就是他们本身的包装类对象,即:

new String() | new Number() | new Boolean()

对象转布尔值

image.png

所以所有的引用类型转成布尔值得到的都为true

Object => String,对象本身具备一个ToPrimitive方法,在javascript的源码并没有暴露出来给我们使用,它的原理是ToPrimitive(input,PreferredType) input是输入的值,preferedType是期望转换的类型,他可以是字符串,也可以是数字。

所以对象转成字符串或者数字就相当于对象调用了ToPrimitive(input,PreferredType),当第一个参数inputDate类型,第二个参数不传,默认第二个参数为String

valueOf()  方法返回指定对象的原始值。 toString()  方法返回一个表示该对象的字符串。

对象转数字类型

ToPrimitive(obj,Number)

  1. 如果obj是基本类型,直接返回;
  2. 否则,调用valueOf方法,如果得到一个原始类型,则返回;
  3. 否则,调用toString方法,如果得到一个原始类型,则返回;
  4. 否则报错。

对象转字符串类型

ToPrimitive(obj,String)

  1. 如果obj是基本类型,直接返回;
  2. 否则,调用toString方法,如果得到一个原始类型,则返回;
  3. 否则,调用valueOf方法,如果得到一个原始类型,则返回;
  4. 否则报错。
我们来实际操练一下:
Number({})
首先我们要明确,这个例子是要将空对象转数字类型;
所以第一步{}不是基本类型,直接返回;
第二步调用valueOf方法,得到的还是一个{}(空对象);
第三步调用toString方法,得到一个"[object Object]"(字符串)。
因为Number是要得到一个数字类型的值,此时只得到了字符串类型,
所以第五步字符串类型转数字类型,即得到的值最终为NaN

这只是其中一个较为好理解的,不要盲目的觉得你都理解了,那Number( [ ] )得到的结果是啥呢?

再聊接下来的内容之前我们需要知道两个方法:

  1. JSON.stringify()  方法将一个 JavaScript 对象或值转换为 JSON 字符串,如果指定了一个 replacer 函数,则可以选择性地替换值,或者指定的 replacer 是数组,则可选择性地仅包含数组指定的属性。
  2. JSON.parse()  方法用来解析 JSON 字符串,构造由字符串描述的 JavaScript 值或对象。提供可选的 reviver 函数用以在返回之前对所得到的对象执行变换 (操作)。
image.png

一元操作符 +

当 + 运算作为一元操作符时,会调用ToNumber()处理该值

+[] //0
+['1'] // 1
+['1','2','3'] --> '1,2,3'  --> NaN
+{} --> "[object Object]" --> NaN

二元操作符 +

v1 + v2 --> ToPrimitive(v1) + ToPrimitive(v2)

  1. lprim = ToPrimitive(v1);
  2. rprim = ToPrimitive(v2);
  3. 如果lprim 是字符串或 rprim是字符串,那么返回ToString(lprim) + ToString(rprim)的拼接结果;
  4. 返回 ToNumber(lprim) 和 ToNumber(rprim)的相加结果。
1 + '1'  // '11'
null + 1 // 1
[] + [] // ''
[] + {} // '' + "[object Object]" --> "[object Object]"
{} + [] // 0 (谷歌V8引擎将{}识别为独立的代码块,而不是作为一个对象)
({} + []) // "[object Object]" + ''--> "[object Object]"
image.png
{} + [] // 0是因为谷歌浏览器识别为:

{

}
// 上面为一个代码片段
+[]
// 下面为一个一元操作符+ 所以转化为0

{} + {} 它的结果取决于浏览器的内核是将第一个{}看作是块级代码 --> NaN 还是空对象 -->  "[object Object][object Object]"
// 

==

== 会比较两边值是否相等,若不是同一种数据类型会进行隐式类型转换;

当执行 x == y

  1. 如果 x 和 y 是同一类型

    1. x 是 undefined ,返回true

    2. x 是 null ,返回true

    3. x 是数字

      x 是 NaN , 返回false(NaN == NaN // false)

    4. x 和 y 指向同一个对象(同一个引用地址),返回 true 否则 返回 false

  2. 如果 x 和 y 不是同一类型 (null == undefined // true) 特例

  3. 1 == 'h' --> 1 == ToNumber('h')

  4. false == '1' --> ToNumber(false) == ToNumber('1')

  5. true == {a: 1} // ToPrimitive({a: 1}) --> 1 == NaN // false

[ ] == ![ ] //true

看到上面这个例子相信你会和我一样一脸茫然,为什么这还能为true呢?首先我们要知道一个运算符优先级 - JavaScript | MDN (mozilla.org)

[] == ![]  //true
1. !天生是为布尔值所准备的取反,所以现将[]转化为布尔值,即true !true --> false

[] == false

2. ToNumber(false) --> 0

[] == 0

3. ToPrimitive(obj,Number)

'' == 0

4. '' --> 0 ,字符串转数字类型

0 == 0

所以答案是true

相信学习到这你和我一样,对javascript这门语言中的类型转换有了一定的了解,希望这篇文章能够帮助到你,有任何问题欢迎评论区留言互动,感谢你的观看!

点赞.jpg