likes
comments
collection
share

深入探索JavaScript神鬼莫测的类型转换

作者站长头像
站长
· 阅读数 28

前言

JavaScript中的类型转换指的是将一种数据类型转换为另一种数据类型的过程。这主要分为两大类:显式(强制)类型转换和隐式(自动)类型转换。

显示类型转换

- 原始值转布尔(Boolean(xx))

- 原始值转数字(Number(xx))

- 原始值转字符串(String(xx))

- 原始值转对象 (new Xxx())

隐式转换

对象转原始值 -- 通常发生隐式转换

所有对象转原始值都会调用toString()

- 任何对象转为布尔值都是true

- {}.toString() 得到由"[object 和 class 和 ]"组成的字符串

- [].toString() 返回由数组内部元素以逗号拼接的字符串

- xx.toString() 返回字符串字面量

valueOf()

能把包装类转为转为原始值

注:只能把原始值对象转为原始值

ToPrmitive(x)(把对象转为原始类型)

是JavaScript中一个抽象操作,它负责将对象转换为原始数据类型。

ToPrimitive(obj, String) => String(obj)

  1. 如果接收到的是原始值,直接返回值
  2. 否则,调用toString方法,如果得到原始值,返回值
  3. 否则,调用valueOf方法,如果得到原始值,返回值
  4. 否则,报错

ToPrimitive(obj, Number) => Number(obj)

  1. 如果接收到的是原始值,直接返回值
  2. 否则,调用valueOf方法,如果得到原始值,返回值
  3. 否则,调用toString方法,如果得到原始值,返回值
  4. 否则,报错

二元操作符

v1 + v2

ToPrimitive走的是转Number类型的步骤

  1. lprim = ToPrimitive(v1)
  2. rprim = ToPrimitive(v2)
  3. 如果 lprim 或者 rprim 是字符串,那么就ToString(lprim)或者ToString(rprim) 再拼接
  4. 否则,那么就ToNumber(lprim) + ToNumber(rprim)(ToNumber是JavaScript中的另一个抽象操作,它的目的是将给定的值转换为一个数字(Number)类型)

==

== 运算符在比较前会执行类型转换

问:1数字 和 '1'字符串相等吗?

深入探索JavaScript神鬼莫测的类型转换

问:两个空数组相等吗?

let a = []
let b = []
console.log(a == b);

打印结果

深入探索JavaScript神鬼莫测的类型转换

分析

a和b不是同一个数组,js引擎在执行这段代码会先生成一个全局上下文调用栈,又因为对象可以无限大,所以对象会被放入堆当中,a和b会被赋一个值,这个值是引用地址,指向堆中相应地址的值。

深入探索JavaScript神鬼莫测的类型转换

显示类型转换

原始值转布尔(Boolean(xx))

在Number类型中 0, NaN会被转成false,其他会被转成true。

console.log(Boolean(1));
console.log(Boolean(0));
console.log(Boolean(-1));
console.log(Boolean(NaN)); // NaN是number类型

打印结果

深入探索JavaScript神鬼莫测的类型转换

在String类型中,空字符会被转为false,其他字符被转为true。

console.log(Boolean('hello'));
console.log(Boolean(''));

打印结果

深入探索JavaScript神鬼莫测的类型转换

在Boolean类型中,false会被转为false,true被转为true。

console.log(Boolean(false));
console.log(Boolean(true));

打印结果

深入探索JavaScript神鬼莫测的类型转换

Undefined 和 Null都被转为false

console.log(Boolean(undefined));
console.log(Boolean(null));

打印结果

深入探索JavaScript神鬼莫测的类型转换

原始值转数字(Number())

字符串转数字

console.log('123')
console.log(Number(''));
console.log(Number(' '));
console.log(Number('hello'));

打印结果

深入探索JavaScript神鬼莫测的类型转换

布尔值转数字

console.log(Number(true));
console.log(Number(false));

打印结果

深入探索JavaScript神鬼莫测的类型转换

Undefined和Null转为数字

console.log(Number(undefined));
console.log(Number(null));

打印结果

深入探索JavaScript神鬼莫测的类型转换

官方文档

深入探索JavaScript神鬼莫测的类型转换

原始值转字符串(String())

直接转换为字符串

console.log(String(123));
console.log(String(true));
console.log(String(false));
console.log(String(undefined));
console.log(String(null));

打印结果

深入探索JavaScript神鬼莫测的类型转换

原始值转对象(new Xxx())

通过new 一个构造函数得到一个实例对象

深入探索JavaScript神鬼莫测的类型转换

对象转原始类型

任何对象转为布尔值都是true

let b = []

if(b) { // Boolean(b)
    console.log('hello');
}

打印结果

深入探索JavaScript神鬼莫测的类型转换

{}.toString() 得到由"[object 和 class 和 ]"组成的字符串

深入探索JavaScript神鬼莫测的类型转换

[].toString() 返回由数组内部元素以逗号拼接的字符串

深入探索JavaScript神鬼莫测的类型转换

valueOf()

深入探索JavaScript神鬼莫测的类型转换

分析

没转成功,以为a是数组对象。

深入探索JavaScript神鬼莫测的类型转换

分析 s是原始值对象,valueOf()只能把原始值对象转为原始值。

ToPrimitive(对象转原始值的原理)

  1. 把对象转为String类型,会先调用toString()方法,如果toString()方法没有转过来,再调用valueOf()方法。
  2. 把对象转为Number类型,会先调用valueOf()方法,如果valueOf()方法没有转过来,再调用toString()方法。

示例:

深入探索JavaScript神鬼莫测的类型转换

分析 +是指转为Number类型,对象转为原始类型,说明要借助ToPrimitive,且是转为Number类型,走第二步,调用valueOf() => []还是一个空数组,接下来再调用toString() => ''变成了一个空字符串,再把空字符串转为Number类型就是0。

二元操作符

示例一

1 + '1' => '11' 为什么?

分析

先执行ToPrimitive(1) + ToPrimitive('1') => 1 + '1','1'是字符串,再执行toString(1) + toString('1') => '1' + '1' =>'11'

示例二

深入探索JavaScript神鬼莫测的类型转换

分析

先执行ToPrimitive([]) + ToPrimitive({}) => '' + '[object Object]',都是是字符串,再执行toString('') + toString('[object Object]') => '' + '[object Object]' =>'[object Object]'

示例三

深入探索JavaScript神鬼莫测的类型转换

先执行ToPrimitive(null) + ToPrimitive(1) => null + 1,无字符串,再执行ToNumber(null) + ToNumber(1) => 0 + 1 => 1

关于 ==

js官方文档 深入探索JavaScript神鬼莫测的类型转换

示例一

1 == {}的执行结果是什么?

深入探索JavaScript神鬼莫测的类型转换

分析 根据官方文档,等号有一边是对象,所以执行1 == ToPrimitive({}),有个运算符 ==,所以ToPrimitive会执行Number的步骤,根据上文得知ToPrimitive({}) => {}.valueOf() => {} => {}.toString() => '[object Object]',此时再把字符串转为数字类型 '[object Object]' => NaN 于是1 == NaN被判成false。

示例二

[] == ![]的执行结果是什么?

深入探索JavaScript神鬼莫测的类型转换 分析

  1. !的优先级大于 ==所以先执行![],又因为!的执行步骤是先转换为布尔值再取反,所以执行Boolean([]) => true(对象转为布尔值是true),取反为false,得到 [] == false
  2. 根据官方文档一边是布尔值时,[] == ToNumber(false) => [] == 0
  3. []是一个对象,又有 ==,执行ToPrimitive([])的Number步骤,[] => '',所以 '' == 0
  4. 又因为''是字符类型,执行ToNumber('') => 0,0 = 0返回true。

结语

内容比较多,没看明白需要自己梳理一下哦。

深入探索JavaScript神鬼莫测的类型转换

转载自:https://juejin.cn/post/7371011013432229926
评论
请登录