《You dont know JS》强制类型转换

时间:2022-12-29 13:30:24

强制类型转换

将值从一种类型转换为另一种类型通常称为类型转换,这是显式的情况。隐式的情况被称为强制类型转换

在书中,作者还提出一种区分方式:

类型转换发生在静态类型语言的编译阶段,强制类型转换发生在动态类型语言的运行时。

JS天生的动态类型语言,所以JS中统一讲强制类型转换。


一、JS中的强制类型转换

首先看如下所示代码:

var a = 42;
var b = a + ''; // 隐式强制类型转换
var c = String(a); // 显式强制类型转换

相较于,第三行代码使用String对变量a进行封装而言,第二行代码的类型转换并非那么明显,更像是'+'操作符的副作用,所以我们把这种情况称为隐式强制类型转换,而显式的通过原生函数封装的方式则称为显式强制类型转换。当然,这只是作者的一种观点而已,但是这种观点对于区分这两种类型转换还是有好处的。


二、JSON.stringify()

如果要将对象字符串化,可以使用JSON.stringify()。这个方法可以带参数,参数可以是以下两种情况:

  1. 参数是一个字符串数组,数组元素是要执行序列化的对象的属性名称:
var a = {
b: 1,
c: '1',
d: [1,2,3]
}; JSON.stringify(a, ['b', 'c']); // "{"b":1,"c":"1"}"
  1. 参数是一个函数,这个函数有两个参数,key和value,这个函数会首先对要序列化的对象自身调用一次,然后对对象的每个属性调用一次,然后如果对象的属性值是可迭代的,会继续对属性值中的每个属性再依次调用。
var a = {
b: 1,
c: [1,23,3]
}; JSON.stringify(a, function(k, v){
console.log('key:',k,' value:',v);
return v;
})

打印输出如下:

key:   value: {b: 1, c: Array(3)}
key: b value: 1
key: c value: (3) [1, 23, 3]
key: 0 value: 1
key: 1 value: 23
key: 2 value: 3

JSON.stringify的执行结果:

"{"b":1,"c":[1,23,3]}"

JSON.stringify还有第三个参数,可以指定缩进符,让生成的字符串更容易被阅读:

JSON.stringify(a, null, 2);

输出结果:

"{
"b": 1,
"c": [
1,
23,
3
]
}"

默认是空格缩进,所以2表示缩进两个空格,你也可以传入别的字符。


三、假值对象

这一点牵扯到了其他值向布尔值的强制类型转换。日常开发中我们经常用到如下所示类型的代码:

var a = '111';
if (a) {
...
}

if语句对a做了一个隐式强制类型转换,我们知道空字符串会被转换为false,非空就是true,包括'0'这种情况。

ES规范列举如下几种会转为假值的值:

  • undefined
  • null
  • false
  • +0, -0, NaN
  • ''

除了这几种值,我们可以认为别的情况都会被转为true。包括空对象{}。但是,还存在一种假值对象,会被转为false。

作者举了一个document.all的类数组对象,会被转为false。现实情况确实是这样。但是似乎这种假值对象并不是很多,多数作为坑存在,我觉得知道有这么一个东西存在就可以了。


四、parseInt()和Number()

  • paeseInt():解析字符串中的数字
  • Number():将字符串强制类型转换为数字

解析允许字符串中含有非数字字符,解析从左到右,遇到第一个非数字字符停止,返回第一个非数字字符之前的所有数字。

转换不允许字符串含有非数字字符,否则返回NaN。

这两种方式各有各的使用场景。


五、||和&&

在JS中,||和&&这两个运算符有一些特殊,如果接触过java、C等语言。我们可能会想当然的把它们称作逻辑运算符,返回值为true或false。但是在JS中,这两个运算符的返回值并不全是true和false,而是返回两个操作数中的一个。

var a = 1;
var b = "2";
var c = {};
var d = true; a || b; // 1
a && b; // "2" b || c; // "2"
b && c; // {} c || d; // {}
c && d; // true

在JS中,||和&&操作符会首先对第一个操作数执行判断,如果值不是布尔值,首先执行强制类型转换:

  • 对“||”而言,如果第一个操作数强制类型转换后为true,则直接返回第一个操作数,否则,直接返回第二个操作数。
  • 对“&&”而言,如果第一个操作数强制类型转换后为false,则直接返回第一个操作数,否则,直接返回第二个操作数。

所以,现在我们就能更好的理解如下所示的这种代码的执行机制到底是怎么回事了:

var a = '1';
var b = '2'; if (a && b) {
...
}

首先,(a && b)这个表达式我们知道返回值是'2',然后if语句对这个结果执行了隐式强制类型转换,转换后的结果为true。


六、宽松相等和严格相等

在了解了强制类型转换后,我们也就能对=====有一个更清晰的理解。

==允许在相等比较中进行强制类型转换,而===不允许。