上节课我们学习了js中数据的 5 大基本数据类型,还剩一个Object类型没有去介绍,当然了,这节课我们暂时还不介绍这个类型,我们会在后续面向对象环节的时候来介绍,那么这节课我们来说什么呢?也是我们一个基础的内容了,就是基本数据类型之间的相互强制转换。

回顾

在开始这节课的内容之前,我们来对上节课的内容来做一个简单的回顾:

  • js拥有 5 种基本数据类型和 1 中引用数据类型
  • Number类型分为整数和浮点数
  • String类型就是由一个个字符组成并用成对的引号括起来的数据结构
  • Boolean类型只有两个值truefalse,用来做逻辑判断
  • Null值只有一个值就是null,专门用来表示一个空对象,所以null的类型实际上是Object
  • Undefined类型就只有一个undefined

以上就是上节课我们所学习的数据类型的大致提纲,那么接下来我们就开始介绍一下关于数据类型之间的强制转换。

数据类型转换概述

我们这节课的内容是数据类型转换,那么什么是数据类型转换呢?我觉得这个词很容易理解,就是把一种类型转为另一种类型嘛,就好比你抓了一把大米,然后把这把大米经过一系列处理变成一碗粥。那么这个处理的过程是什么?就是所谓的类型转换。

那么我们js中的类型转换也就是差不多的意思,比如我这边有一个数字 123,我要把这个数字转为一个字符串变成"123",这就叫做类型转换。但是呢我们有 6 种数据类型,这样两两排列组合的话是不是有太多种情况?其实并不是这样,我们实际上所说的类型转换只是在基本数据类型之间转换。

但是那好像也很多啊,当然了,我们来分析一下,我们可能会把一个数据从其他数据类型转为Null或者Undefined型吗?这两个类型就只有一个值,我们要用的话直接赋值就可以了,干嘛要转换呢,没有意义。所以说实际开发中的类型转换只是把其他类型转为StringNumber再或者是Boolean型。这样一做限制是不是情况就少了很多呢?

那么接下来我们就来介绍一下各个类型之间的转换。

将其他类型转为String

其实这个类型转换的情况是最简单的一个,基本上我们字面量长什么样子,转换成String之后也还长什么样子,就好比现在疫情严重,你在外地工作回不了家,家人想你了,也见不到,搁过去车马和书信都很慢,而且书信只能写一些想说的话,也见不到本尊。现在科技发展地多快啊,疫情严重回不了家,和家人减不了面,那么打一个视频呗,你长什么样,家人在对面从手机里看见的就是什么样。

这和其他类型转成字符串类型是一个效果,那么我们怎么才能将其他类型转为字符串类型呢?其实将其他类型转为字符串有两种方式:

  • 调用被转换的变量或者字面量的toString方法
  • 调用String函数,并将被转换的变量或者字面量作为参数传给String函数

上面我列出了两种方法大家可能会觉得陌生,这两个是什么?什么叫方法,什么又是函数?那个叫做参数的又是什么东西?这些暂时大家都不用去在意,我们后面的课程中都会一一详细介绍,现在只需要知道有这么三个东西,一个叫方法,一个叫函数,还有一个叫参数。

那么我们先来介绍方式一:调用被转换的变量或者字面量的toString方法。

这句话是什么意思呢我们要想理解一句话,那么要先搞清楚这句话的结构,所谓的主谓宾,这句话谁是主语?是不是没有主语?省略了,那么谓语是谁?是不是调用?这是一个动作,什么动作?调用。那么一个省略掉的主语完成了一次调用动作,那么调用了什么呢?我们的宾语又是什么?是不是toString方法?

这句话简单地说就是:某某某调用toString方法,那么我们那句“被转换的变量或字面量”又是什么?在中文语法中,这个是不是用来对宾语补充说明的,所谓的补语?那么这句话的意思就说明,我们要转换类型的变量和字面量拥有一个叫做toString方法的东西,当我们调用这个东西的时候,就可以将这个变量或者字面量转为字符串。

从这句话中我们得到了一个信息,就是我们想要转换类型的东西已经准备好现成的机关了,只要我们启动或者说调用那个机关,就能把它转换成字符串。那么我们怎么调用呢?

这里我们要记住,当我们说调用xxxyyy方法的时候,在代码里面就表示为xxx.yyy()。所以说我们在代码中来尝试一下吧:

// 声明并赋值
var a = 123;
// 输出变量 a 的类型和值
console.log(typeof a);
console.log(a);
// 调用变量 a 的 toString 方法
a.toString();
// 输出调用了 toString 方法之后 a 的类型和值
console.log(typeof a);
console.log(a);

我们来看一下代码,我们在上面的代码块中用注释写得很清晰,首先声明并赋值一个变量,然后调用这个变量的toString方法,而且我们在调用toString方法前后都输出了这个变量的类型和值,那么我们来看一下结果:

image-20220330101405163

结果好像不太对啊,我们刚开始声明赋值变量a,输出a的类型是一个数字类型,很正常,但是我们调用了atoString方法了,理论上应该把a转成字符串才对啊,这是为什么呢?

是这样,toString方法是不会修改原来变量的值的,就好像别人给你拍一张照片,然后在PS里面给你瘦脸是没法在现实中给你达到减肥瘦脸的效果的。toString会返回把变量转为字符串之后的值。可能到这里大家又要问了,什么叫返回啊?这里大家先不需要理解什么叫返回,后面的课程我们会进一步解释,现在大家就简单理解成,这个方法会而外生成一个新的值,但是并不会修改原来的变量的值。

那么我们要是想修改原来的变量怎么做呢?我们来看一下:

// 声明并赋值
var a = 123;
// 输出变量 a 的类型和值
console.log(typeof a);
console.log(a);
// 调用变量 a 的 toString 方法,并将产生的值赋给变量 a
a = a.toString();
// 输出调用了 toString 方法之后 a 的类型和值
console.log(typeof a);
console.log(a);

我们就这样直接修改一下代码,和之前的代码唯一的区别就是我们把调用变量a得到的值重新赋给了变量a,这样的话就修改了原来的变量,那么我们看一下结果吧:

image-20220330102251959

我们看到这一次两次输出就符合我们的预期了,而且输出内容中的颜色都变了,因为第二次输出的是字符串类型的 "123"。但是我们之前在说方式一的时候说的这个toString方法是属于变量或者字面量的,这是为什么呢?因为我们可以直接通过字面量来调用这个方法,比如说像这样:

console.log(typeof true);
console.log(true);
console.log(typeof true.toString());
console.log(true.toString());

我们来看上面这段代码,我们先是输出字面量true的类型和值,那么输出的肯定就是booleantrue。紧接着我们又输出ture这个字面量调用toString方法之后得到的值的类型和值,那么输出的是什么呢?还是说会报错呢?我们来看一下:

image-20220330102916861

我们看见第一次输出和我们预期一致,第二次输出类型是字符串,值是字符串类型的"true"所以说字面量可以直接调用toString方法,只不过我们通常还是通过变量调用toString方法比较多一些。

那么到这大家可能会觉得将其他类型转为字符串讲到这可以了,有这个方式一就够了,还要方式二干嘛呢,其实不然,因为方式一是有局限性的,比如我们将NullUndefined类型转为StringtoString方法会怎么样呢?

var a = null;
var b = undefined;
console.log(a.toString());
console.log(b.toString());

image-20220330103409105

image-20220330103456565

我们看到直接报错了,而且两个都是同一种错误,说nullundefined没有toString方法。所以说方式一是没法满足所有将其他类型转为字符串的需求场景的。那么我们就要请我们的方式二出场了:调用String函数,并将被转换的变量或者字面量作为参数传给String函数。

那么这句话里面出现了两个我们不理解的词,函数和参数,当然后续课程中我们会详细介绍,这里大家只要知道有这么两个东西就行了。

那么这句话是什么意思?还是一样分析句子结构,我们可以简单地将这个句子先拆分成两个句子,第一个句子省略主语,谓语是调用,宾语是String函数,简单来说我们方式二就是调用了一个函数,再看第二个句子,依然省略主语,谓语是一个传入参数的动作,宾语是String函数。

那么这句话怎么理解呢,我们可以通过调用String函数来将某个变量和字面量转为字符串,但是在调用String函数的时候要把我们需要转换的变量或者字面量给这个函数当参数用,就好比我渴了,我可以去买一瓶矿泉水喝,但是我去买矿泉水的时候要带钱。这个参数就好比是这个函数能成功调用的一个前提条件。就好像我买矿泉水的前提条件是有钱。

那么好,两个动作,调用和传参,怎么调用而又怎么传参呢?我们这里也浅谈一下吧,当我们说调用xxx函数时,在代码中就表示为xxx(),这就叫函数的调用,那么我们说把yyy作为参数传给xxx函数时,在代码中就表示为xxx(yyy)。那么我们在代码中来实现一下看看吧:

var a = String(null);
var b = String(undefined);
console.log(typeof a);
console.log(a);
console.log(typeof b);
console.log(b);
var c = 123;
c = String(c);
console.log(typeof c);
console.log(c);

我们来看上面这段代码,前两行将字面量nullundefined分别传给String函数并声明赋值给变量ab,然后输出变量ab的类型和值,然后后面是调用String函数来讲数字类型的变量c转为字符串类型,我们来看一下结果:

image-20220330110438566

一切都和我们预期的一样,都转为了字符串类型了,所以说方式二是可以满足所有场景的。而且补充说一点,String函数和toString方法一样,都不会改变原来变量的值,而是返回一个新的值,我们这里就不再演示了。

虽然说有两个方式可以用,但是我们通常都用toString方法多一点,更加能够体现面向对象的思想,只有在有要对Null或者Undefined有数据转换的需求时才会使用String函数。

将其他类型转为Number

讲完了将其他类型转为String类型之后我们后面的内容就方便多了,因为大家之前没见过的概念基本上都在String中解释了,在后续的内容中就不再赘述了。

那么接下来我们来讲然后将其他数据类型转为Number类型,和转String类型一样,将其他类型转为Number类型也有两种方式:

  • 调用Number函数,并将要被转换的变量或者字面量作为参数传给Number函数
  • 调用parseIntparseFloat函数,并将要被转换的变量或者字面量作为参数传给parseIntparseFloat函数

看到这可能很多人要问:没有toNumber方法吗?没错,这个真没有,只有上面我们列出来的两种方式。

那么我们先来看一下方式一:调用Number函数,并将要被转换的变量或者字面量作为参数传给Number函数。这个句子是不是很熟悉了?和转String的方式二是不是不能说很像吧,可以说几乎是一模一样。那么我们就不做句子结构分析了,因为和转String方式二一模一样,连用法也都一样,那么直接提炼有效信息:

两个动作,调用和传参,代码中表示为xxx(yyy),那么我用代码实现一下吧:

var a = "123";
var b = "123.123";
var c = "123abc";
a = Number(a);
b = Number(b);
c = Number(c);
console.log(typeof a);
console.log(a);
console.log(typeof b);
console.log(b);
console.log(typeof c);
console.log(c);

我们来看这段代码,我们声明并赋值了 3 个变量,而且这 3 个变量都是字符串类型的,因为我们一旦提到将其他类型转为数字,那么首先想到的是不是将字符串转为数字?那么我们来看一下用Number函数将字符串转为数字的结果是什么样子呢?首先我们前两个变量的字符串是不是都是纯数字的字符串啊?一个是整数另一个是浮点数。但是第三个就不是纯数字的了,里面还有其他的字母,那么我们看一下分别是什么样子吧:

image-20220330112612474

我们看见前两个纯数字的字符串都正常转换成了数字,但是最后一个不是纯数字的字符串经过转换之后呢得到的是一个NaN,所以说只有纯数字字符串才能正常通过Number函数转成一个正常的数字,否则得到的就是NaN。但是有没有特殊情况呢?当然有的我们来看特殊情况:

var a = "";
var b = "     ";
a = Number(a);
b = Number(b);
console.log(a);
console.log(b);

我们看上面这段代码,两个变量,其中一个,两个双引号之前什么字符都没有,这个叫做空字符串。另一个双引号之间只有空格,那么我们看一下转换之后输出是什么,这次我们就不输出类型了,因为调用了Number函数得到的值一定是Number类型。

image-20220330113244865

我们来看,这两个输出的都是 0,这就是字符串中的特殊情况了,空字符串和全是空格的字符串转数字类型得到的是 0。

那么字符串我们到这就算把对Number函数的调用的所有情况说完了,那么其他数据类型呢?我们来看一下:

var a = true;
a = Number(true);
var b = false;
b = Number(false);
var c = null;
c = Number(null);
var d = undefined;
d = Number(undefined);
console.log(a);
console.log(b);
console.log(c);
console.log(d);

我们来看这段代码,我们分别将Boolean类型的truefalse转为数字类型,然后将nullundefined转为数字类型,到这一步,我们就完成了将所有基本数据类型都转为数字类型了。那么我们来看一下输出结果是什么样子的:

image-20220330113843041

诶,输出的结果还是挺丰富的,我们通过对比代码和结果得到一个结论,ture转为数字会转为 1,而false则会转为 0,这也很好理解,计算机底层都是用二进制 1 和 0 来表示真假的嘛,所以Boolean类型自然会和 1 还有 0 相对应。而null代表的是空对象,所以转为数字也就是 0,然后我们看最后一个,undefined转成数字类型是NaN,这个也很好理解,因为undefined代表未定义,但是具体是什么我们不知道,它也不像null代表空,既然这个东西不为空,也不知道是什么,但是唯一知道的是这个东西不是数字,往数字类型转换刚好有一个东西代表着不是数字,那么自然这俩神奇的存在就相互联系在了一起。

以上呢就是将其他类型转为Number类型的方式一,而且这个方式已经可以满足所有场景了,那么为什么还要有方式二呢?其实方式二是有它特殊存在的意义的。我们之前说不是纯数字的字符串通过调用Number函数转为数字会得到NaN,但是实际开发中我们真的需要将不是纯数字的字符串转为数字怎么办呢?比如css中的200px,我们要在200px的基础上加上20px,那么我们能直接拿200px20px的字符串直接做加法运算吗?肯定不行的啊,而且我们也不能通过Number函数来拿到200px中的 200,那么我们怎么办?

这个时候我们就要用到方式二了:调用parseIntparseFloat函数,并将要被转换的变量或者字面量作为参数传给parseIntparseFloat函数。那么这句话和方式一有区别吗?是不是几乎也没有区别?只不过是有两个函数可以调用。其他的结构都是一样的。实际上这些函数的用法都是一样的。

那么我们来介绍一下这两个函数,这两个函数其实是专门用来处理这种不是纯数字的字符串的。从函数名的字面意思上来看,两个函数:一个是解析整数,另一个是解析浮点数。也是很清晰明了了,我们来用代码实现一下这两个函数的用法:

// 用 parseInt 函数解析包含整数和字母的字符串
var a = "123asd";
a = parseInt(a);
console.log(a);
// 用 parseInt 和 parseFloat 函数分别解析包含浮点数和字母的字符串
var b = "123.123asd"
var b1 = parseInt(b);
b = parseFloat(b);
console.log(b1);
console.log(b);
// 用 parseInt 和 parseFloat 函数分别解析包含省略了 0 的浮点数和字母的字符串
var c = ".123asd";
var c1 = parseInt(c);
c = parseFloat(c)
console.log(c1);
console.log(c);
// 用 parseInt 和 parseFloat 函数分别解析以字母开头的包含浮点数和字母的字符串
var d = "asd123.123";
var d1 = parseInt(d);
d = parseFloat(d);
console.log(d1);
console.log(d);

我们来看这段代码,这次的代码有点多,所以我在代码中添加了注释,我们先是直接解析整数。然后第二部分,用parseInt函数去解析一个包含浮点数的字符串看是什么结果,然后再用parseFloat函数去直接解析这个包含浮点数的字符串看看结果,并且对比一下二者的区别。第三部分呢,我们分别用这两个函数去解析一个以小数点开头的字符串,因为通常在计算机中很多情况下小于 1 的浮点数都喜欢把前面的 0 省略掉,比如0.5写成.5,那么这样的话这两个函数解析出来的结果又有什么区别吗?最后一个部分,就是这个字符串里包含有数字,但是呢字符串既不以数字开头也不以小数点开头,那么这个结果会是什么样子的呢?我们来看一下结果吧:

image-20220330130010894

为了方便区分这 4 个部分我们用一行*组成的字符串来将各个部分隔开,那么我们先来看第一个部分的结果,成功取出了数字 123,这个没有什么好解释的,因为这个函数就是用来解析并提取字符串中的整数的,所以成功取出了字符串中的数字。

再来看第二部分:首先是用parseInt函数的结果,这个字符串中包含的是123.123这个浮点数,而我们得到的值是一个整数,这是为什么?我们来推测一下,这个字符串里面虽然包含一个浮点数,但是parseInt函数是提取整数的,那么浮点数的小数位肯定会被舍弃掉。好像挺合理,那么我们暂时就当是这个原理。再来看下面这一行是parseFloat函数的结果,直接取出了浮点数123.123,那么这个也是没有什么可解释的了,以为这个函数就是解析并提取字符串中的浮点数的。

再来看第三部分吧,首先是parseInt函数的结果,得到的是一个NaN,这是为什么呢?按照我们刚刚在第二部分分析的结论,parseInt函数检测到这是一个浮点数会自动舍弃小数位,那么得到的应该是 0 才对啊,但是结果却是NaN,再来看parseFloat函数的结果0.123,这个倒是很正常的结果。这二者为什么会有这么大的区别呢?

这就要从parseIntparseFloat函数的解析逻辑来说了。

parseInt函数是只解析整数的,这个函数会从一个字符串的第一个字符开始检查,检查第一个字符是不是数字,如果第一个字符不是数字就直接返回一个NaN,如果是数字,就继续检查第二个字符,到第二个数字也是同样的逻辑,如果不是数字,那就直接停止,后面的也都就一并丢弃了,然后只返回前面是数字的字符并且直接转为数字,也就是说底层逻辑就是先从第一个字符一直一个一个往后检查,知道遇到第一个不是数字的字符,直接截断生成一个新的纯数字的字符串,然后再通过Number函数实现将这个纯数字的字符串转为数字。

那么parseFloat函数呢?其实和parseInt函数的逻辑是一样的,只不过这个函数会比parseInt函数多检查一个小数点,这个函数会从一个字符串的第一个字符一个一个往后检查这个字符是不是数字或者小数点,直到遇到第一个不是数字或小数点的字符或者遇到第二个小数点就直接把字符串截断并生成一个新的纯数字的字符串,然后通过Number函数来讲这个新的字符串转为数字。

当然这里为什么说第一个不是数字或小数点的字符或者遇到第二个小数点呢?我们来看一下:

var a = "1.2asd";
var b = "1.2.3.4";
a = parseFloat(a);
b = parseFloat(b);
console.log(a);
console.log(b);

我们来看上面这段代码,变量a包含了一个浮点数和一些字母,这个字符串里面只有一个小数点,变量b倒是没有字母,但是有好几个小数点,那么结果会是什么样子呢?

image-20220330132443812

匹配变量a,从第一个字符开始检查,是数字,到了第二个字符是第一个小数点,再往后还是数字,到了第 4 个字符,是个字母,既不是数字也不是小数点,那么截断,生成了一个新的纯数字字符串"1.2",然后通过Number函数转为数字,这个很好理解。

再看变量b,从第一个字符检查,是数字,到了第二个字符是第一个小数点,再往后是数字,到了第 4 个字符,是第二个小数点,我们有见过哪个浮点数有两个小数点或者更多个小数点吗?是不是没有?每个浮点数都只有一个小数点,所以说到了第二个小数点,直接截断,生成了一个新的纯数字字符串"1.2",然后通过Number函数转为数字。

而且最后还有一点这两个函数都是从字符串的第一个字符开始检查,如果第一个字符就不符合两个函数各自检查的条件的话那么就不会再往后检查了,直接返回NaN,这也解释了为什么上面那段代码的第四部分这两个函数的值都是NaN

以上就是关于js中将其他基本数据类型转为Number型的两个方式。最后补充一点,如果传入parseInt或者parseFloart函数的参数不是字符串类型的话,那么函数底层会先自动将参数转为字符串然后再进行后续的解析和处理。

将其他类型转为Boolean

其实到了这一步本节课即将接近尾声了,将其他类型转为Boolean其实是非常简单的,因为Boolean类型的数据就只有两个值,要么是true,要么是false那么我们只要知道那些是false,其余的都是true就行了啊,那么我们怎么将其他类型的数据转为Boolean类型呢?只有一个方式就是调用Boolean函数,没错,这次又是谜底就在谜面上。

那么我们来介绍一下这个方式:调用Boolean函数,并将要被转换的变量或者字面量作为参数传给Boolean函数,这个格式真的是再熟悉不过了,转String的方式二,转Number的两种方式都是这个句子结构。我们就不多做分析了,因为用法和前面我们所遇到的方式都是完全一样的,那么我们直接来实现吧。当然在实现之前我们来列举一下将其他类型转为Boolean的情况:

  • StringBoolean,而String分 3 种情况
    • 随机非空字符串,比如"asa3343f.3_^%&*""askja 372497 asj \n\t"
    • 空字符串:""
    • 全是空格的字符串:" "
  • NumberBoolean,而Number也分了几种情况:
    • ± Infinity
    • 正负整数和正负浮点数
    • 0
    • NaN
  • NullBoolean
  • UndefinedBoolean

那么我们来看代码:

var a = "asd432 asda";
a = Boolean(a);
console.log(a);
var b = "";
b = Boolean(b);
console.log(b);
var c = "     ";
c = Boolean(c);
console.log(c);
console.log("*******************");
var d = Infinity;
d = Boolean(d);
console.log(d);
var d1 = -Infinity;
d1 = Boolean(d1);
console.log(d1);
var e = 2343;
e = Boolean(e);
console.log(e);
var e1 = -284;
e1 = Boolean(e1);
console.log(e1);
var e3 = 324.1342;
e3 = Boolean(e3);
console.log(e3);
var e4 = -324.1342;
e4 = Boolean(e4);
console.log(e4);
var f = 0;
f = Boolean(f);
console.log(f);
var g = NaN;
g = Boolean(g);
console.log(g);
console.log("*******************");
var h = null;
h = Boolean(h);
console.log(h);
console.log("*******************");
var i = undefined;
i = Boolean(i);
console.log(i);

我们这次代码也比较多,我们也是按照上面列举的情况来做了分割,第一部分是字符串的三种情况,第二部分是Number型的几种情况,接下来就是NullUndefined型的情况,那么我们来看一下结果吧:

image-20220330135758041

为了稍微直观一点我们输出了转换之前的变量,我们先来看第一部分,字符串转Boolean,只有第二个空字符串是false,其余的都是true,再来看第二部分NumberBoolean,只有 0 和 NaNfalse,其余都是true,紧接着第三部分和第四部分nullundefinedBoolean都是false

这就是将其他类型转为Boolean类型的结果。

总结

到了这一步,基本数据类型之间的饿相互转换就告一段落了,那么我们接下来对这节课的内容来做一个简单的总结:

  • 基本数据类型之间的数据转换只会将其他数据类型转为StringNumberBoolean
  • 将其他数据类型转为String有两种方式
    • 调用被转换的变量或字面量的toString方法
    • 调用String函数并将被转换的变量或字面量传入函数
  • nullundefined没有toString方法,调用的话会报错,只能通过String函数来转
  • 将其他类型转为Number也有两种方式
    • 调用Number函数,并将被转换的变量或字面量传入函数
    • 调用parseInt或者parseFloat函数,并将被转换的变量或字面量传入函数
  • 第二种方式是专门用来处理非纯数字的字符串的。若传入的参数不是字符串,函数会先把传入的参数转为字符串再进行处理。
  • 将其他类型转为Boolean类型只有一种方式,就是调用Boolean函数,并将被转换的变量或字面量传入函数
  • 其他类型转为Boolean分以下几种情况
    • 字符串转Boolean,除了空字符串为false,其他均为true
    • 数字转Boolean,除了 0 和NaNfalse,其他均为true
    • nullundefinedBoolean均为false

以上便是本节课主要内容,下节课我们进入算数运算符的介绍。

Copyright statement:The articles of this site are all original if there is no special explanation, indicate the source please when you reprint.

Link of this article:https://work.lynchow.com/article/js_basic_grammar_3/