重学前端
此文章为《JavaScript重难点实例精讲》的笔记,记录下以往没注意过的一些js小细节。
JavaScript的基本数据类型
Undefined类型
Undefined类型只有一个唯一的字面值undefined,表示的是一个变量不存在。下面是4种常见的出现undefined的场景。
- 使用只声明而未初始化的变量时,会返回“undefined”。
1 |
|
- 获取一个对象的某个不存在的属性时,会返回“undefined”。
1 |
|
- 函数没有明确的返回值时,却在其他地方使用了返回值,会返回“undefined”。
1 |
|
- 函数定义时使用了多个形式参数,而在调用时传递的参数的数量少于形参数量,那么未匹配上的参数就为“undefined”。
1 |
|
Null类型
Null类型只有一个唯一的字面值null,表示一个空指针对象,这也是在使用typeof运算符检测null值时会返回“object”的原因。
下面是3种常见的出现null的场景。
- 一般情况下,如果声明的变量是为了以后保存某个值,则应该在声明时就将其赋值为“null”。
1 |
|
- JavaScript在获取DOM元素时,如果没有获取到指定的元素对象,就会返回“null”。
1 |
|
- 在使用正则表达式进行捕获时,如果没有捕获结果,就会返回“null”。
1 |
|
Boolean类型
一些隐式转换情况
Object类型转换为Boolean类型
· 当object为null时,会转换为false。
· 如果object不为null,则都会转换为true,包括空对象{}。
Number类型转换为Boolean类型
· 0和NaN会转换为false。
· 除了0和NaN以外,都会转换为true,包括表示无穷大和无穷小的Infinity和-Infinity。
Function类型转换为Boolean类型
任何Function类型的值都会转换为true。
Number类型
一些隐式转换情况
Undefined类型转换为Number类型
Undefined类型只有一个字面值undefined,直接转换为NaN。
String类型转换为Number类型
- 只包含数字则会转换为十进制数,如 “0123”转为123
- 如果字符串中包含的是有效的浮点数,则同样按照十进制转换,“1.23”转为1.23
- 如果字符串中包含有效的十六进制格式,则会按照十进制转换,如“0x3f”会转换为63
- 如果是空字符串,则转换为0
- 如果字符串中包含了除上述格式以外的字符串,则会直接转换为NaN
Object类型转换为Number类型
如果值为对象类型,则会先调用对象的valueOf()函数获取返回值,并将返回值按照上述步骤重新判断能否转换为Number类型。如果都不满足,则会调用对象的toString()函数获取返回值,并将返回值重新按照步骤判断能否转换成Number类型。如果也不满足,则返回“NaN”。
1 |
|
关于Number类型经常遇到的一个面试题
设想这样一个场景,存在一个数组,数组中的每个元素都是Number类型的字符串[‘1’,’2’, ‘3’, ‘4’],如果我们想要将数组中的元素全部转换为整数,我们该怎么做呢?
下意识的是不是想到这样的代码
1 |
|
其实这就是一个藏在map()函数与parseInt()函数中的隐形坑。
1 |
|
parseInt()函数接收的第二个参数实际为数组的索引值,所以实际处理的过程如下所示
1 |
|
任何整数以0为基数取整时,都会返回本身,所以第一行代码会返回“1”。
第二行代码parseInt(‘2’, 1),因为parseInt()函数对应的基数只能为2~36,不满足基数的整数在处理后会返回“NaN”;
第三行代码parseInt(‘3’, 2),表示的是将3处理为二进制表示,实际上二进制时只有0和1,3超出了二进制的表示范围,无法转换,返回“NaN”;
第四行代码parseInt(‘4’, 3),与第三行类似,4无法用三进制的数据表示,返回“NaN”。
1 |
|
isNaN()函数与Number.isNaN()函数对比
在判断NaN时,ES5提供了isNaN()函数,ECMAScript 6(后续简称ES6)为Number类型增加了静态函数isNaN()。
1 |
|
String类型
定义字符串有三种方式
- 字符串字面量方式,var a = ‘string’
- 直接调用String()函数,var a = String(‘hello’)
- new String()构造函数,var a = new String(‘hello’)。ps:new运算符生成的字符串是字符串对象。
1 |
|
基本字符串在作比较时,只需要比较字符串的值即可;而在比较字符串对象时,比较的是对象所在的地址。
str4、str5和str6,因为是使用new运算符生成的String类型的实例,所以在比较时需要判断变量是否指向同一个对象,即内存地址是否相同,很明显str4、str5、str6都是在内存中新生成的地址,彼此各不相同。
为什么采用字面量方式定义的字符串也可以使用indexOf()、substring()、slice()等函数呢?
实际上基本字符串本身是没有字符串对象的函数,而在基本字符串调用字符串对象才有的函数时,JavaScript会自动将基本字符串转换为字符串对象,形成一种包装类型,这样基本字符串就可以正常调用字符串对象的方法了。
引用数据类型
引用数据类型有不同于基本数据类型的特点,具体如下所示:
- 引用数据类型的实例需要通过new操作符生成,有的是显式调用,有的是隐式调用
- 引用数据类型变量赋值传递的是内存地址
- 引用数据类型的比较是对内存地址的比较,而基本数据类型的比较是对值的比较