JavaScript 学习笔记 之 强制类型转换 (二)

字符串和数字之间的隐式强制类型转换

先看一组例子

			"42" + "0"; //420
			42 + 0; //42

这种情况通常我们会理解为,+运算符的任意一边(或者两遍都)出现了字符串则是字符串拼接

那么再看一组例子

			[1, 2] + [3, 4]; //1,23,4

事实上,正确的解读应该是

如果某个操作数是字符串或者能通过以下操作(从对象)转换为字符串的话,则进行拼接操作

  1. valueOf()
  2. toString()

(事实上是抽象操作ToPrimitive先通过内部操作[[DefaultValue]]检查是否有valueOf方法,如果有并返回基本类型值,就使用该值进行强制类型转换,如果没有就使用toString()的返回值(如果存在)来进行强制类型转换)

这里有个坑是关于{}+[]和[]+{}分别等于0和"[object Object]"的

{}+[]中{}被当做了一个独立的空代码块,不执行任何操作,因此实际上运行的是+[],+作为一元运算符将[]强制转换为数字0

而[]+{}中{}被当做一个值(空对象),因此被转换为""+"[object Object]",结果为"[object Object]"

在代码中我们经常可以看到+""的形式来进行隐式的强制类型转换

			typeof(42 + "") //string

但是要注意一个和显式强制类型转换(String(..))细微的区别

隐式会先对两边的运算数调用valueOf(..)方法,而String(..)则是直接调用toString(..)方法,所以如果自己定义了valueOf(..)方法的返回值跟toString(..)返回值不一致,那么结果也会不一致

		var a = {
			valueOf: function() {
				return 4;
			},
			toString: function() {
				return 42;
			}
		}
		console.log(
			a + "", //4
			String(a), //42
		)

再来看看字符串转数字的情况

			typeof("123" - 0); //number

因为只有数字才会进行-运算(*1,/1也一样,但是不常见),因此"123"字符串被隐式强制转换为了数字(先toString转换为字符串,然后再转换为数字)

布尔值到数字的隐式强制类型转换

布尔值转数字的情况比较少

考虑下面的情形

需要一个函数,当传入的参数中,有且仅有一个参数为true,则返回true

单独进行判定的话,如果有很多参数的时候会很麻烦,这时候可以使用从布尔值转换为数字(0,1)的强制类型转换

		function onlyOne() {
			var sum = 0;
			for(let i = 0; i < arguments.length; i++) {
				sum += !!arguments[i];
			}
			return sum == 1;
		}

隐式强制类型转换为布尔值的情况

  1. if(..)
  2. for(..;..;..) 中第二个
  3. while(..)
  4. ?:三元运算符
  5. || , && 左侧的操作数

以上情况中,会被隐式强制类型转换为布尔值

||和&&

其他语言中的||和&&逻辑运算符返回的都是一个布尔值(true或false)

但是JavaScript中的行为有些不太一样

			"a" || "b" //a
			null || "b" //b

||会首先对第一个操作数进行条件判断(强制类型转换为布尔值)

如果第一个数为true就返回第个数,如果第一个数为false就返回第个数

a||b 大致相当于 a?a:b

			"a" && "b" //b
			null && "b" //null

&&也是首先会对第一个操作数进行条件判断(强制类型转换为布尔值)

如果第一个数为true就返回第个数,如果第一个数为false就返回第个数

a&&b 大致相当于 a?b:a

之所以说大致相当于,是因为当a是一个复杂的表达式(比如有副作用的函数调用)时,它有可能被执行两次

(这里我不太明白,具体什么样的情况才会调用两次呢?如果有知道的,希望能够在评论说下,谢谢)

&&有一种不常见的用法,但在压缩代码中很常用,叫做守护运算符

比如 check && fun()

当check为真的时候才会运行fun(),即前面的表达式为后面的表达式把关 等同于if(check){fun()}

Symbol的强制类型转换

Es6中的Symbol的强制类型转换有个坑

			var sym = Symbol("cool");
			String(sym), //Symbol(cool)
			sym + "" //TypeError

可以看到,显示转换为字符串是可行的,但是隐式转换则会报错

而转换为数字则不管隐式还是显式都会报错

布尔值的话显示隐式都为true

猜你喜欢

转载自blog.csdn.net/Aproducer/article/details/82846685