粥里有勺糖

vuePress-theme-reco 粥里有勺糖    2018 - 2023
粥里有勺糖 粥里有勺糖

Choose mode

  • dark
  • auto
  • light
关于我
备战春秋
  • 心得总结
  • 校招考点汇总
  • 面经汇总
  • 复习自查
技术笔记
  • 技术教程
  • 模板工程
  • 源码学习
  • 技术概念
  • 个人作品
  • 学习笔记
计算机基础
  • 算法与数据结构
  • 操作系统
  • 计算机网络
  • 设计模式
  • 剑指offer
大前端
  • javascript
  • vue
  • html
  • css
  • 🌏浏览器专题
  • Web性能优化
  • regexp
  • node
面试
  • 问解
  • javascript
  • css
  • 手撕代码
  • 性能优化
  • 综合问题
  • 面经汇总
  • 小程序
手撕代码
  • 数据结构与算法
  • javascript
  • css
个人站点
  • GitHub (opens new window)
  • 博客园 (opens new window)
  • 掘金 (opens new window)
线上作品
  • 轻取(文件收集) (opens new window)
  • 个人图床 (opens new window)
  • 考勤小程序 (opens new window)
  • 时光恋人 (opens new window)
  • 在线简历生成 (opens new window)
留言板
Github (opens new window)
author-avatar

粥里有勺糖

285

文章

40

标签

关于我
备战春秋
  • 心得总结
  • 校招考点汇总
  • 面经汇总
  • 复习自查
技术笔记
  • 技术教程
  • 模板工程
  • 源码学习
  • 技术概念
  • 个人作品
  • 学习笔记
计算机基础
  • 算法与数据结构
  • 操作系统
  • 计算机网络
  • 设计模式
  • 剑指offer
大前端
  • javascript
  • vue
  • html
  • css
  • 🌏浏览器专题
  • Web性能优化
  • regexp
  • node
面试
  • 问解
  • javascript
  • css
  • 手撕代码
  • 性能优化
  • 综合问题
  • 面经汇总
  • 小程序
手撕代码
  • 数据结构与算法
  • javascript
  • css
个人站点
  • GitHub (opens new window)
  • 博客园 (opens new window)
  • 掘金 (opens new window)
线上作品
  • 轻取(文件收集) (opens new window)
  • 个人图床 (opens new window)
  • 考勤小程序 (opens new window)
  • 时光恋人 (opens new window)
  • 在线简历生成 (opens new window)
留言板
Github (opens new window)
  • Javascript

    • 简介
    • 获取某年某月的天数
    • 日期格式化
    • 展开多级数组
    • 判断数据类型的方案
    • 文件上传与下载
    • 柯里化
    • 闭包
    • delete
    • 垃圾回收
    • 节流与防抖
    • apply,call,bind
    • blob与file
    • Event Loop
    • Promise
    • 定时器
    • 原型与原型链
    • 作用域
    • 执行上下文栈
    • 变量对象
    • 作用域链
    • ECMAScript规范解读this
    • 执行上下文
    • 参数按值传递
    • 类数组与arguments
    • 浮点数
    • Symbol的用法
    • 箭头函数
    • 类型转换
    • 获取dom元素的方式
    • 浅拷贝与深拷贝
    • ES6+的新语法糖和方法整理
    • 学习过程中学到的一些取巧之法

JavaScript中的类型转换规则

vuePress-theme-reco 粥里有勺糖    2018 - 2023

JavaScript中的类型转换规则

粥里有勺糖 2020-04-14 大前端javascript

# JavaScript中的类型转换规则

先上两张有趣的网图:

图片

图片

可以看出,JavaScript的隐式类型转换是很有意思的(让人摸不着头脑)

同时面试中页通常会遇到类型转换的考(ba)题(gu),比如:

// 哪些为真?
if([])
if({})
if([]==false)
if({}==false)
if([] == ![])
1
2
3
4
5
6

如果看着这题摸不着头脑,大伙儿可以接着往下看

本文较完整的梳理一下常见的类型转换规则与转换场景

一点说明: 文中的值类型等价于所说的基础类型,其范围是(boolean,string,number)

# 向基础类型转换

# 布尔Boolean

# 转换为boolean的方式

常用的两种

  • !!value:取反两次
  • Boolean(value):用Boolean包裹

# 转换为假(false)

  • undefined, null,NaN,'', 0 --> false
点击查看示例代码
console.log(!!undefined);
console.log(!!null);
console.log(!!NaN);
console.log(Boolean(''));
console.log(Boolean(0)); 
1
2
3
4
5

# 转换为真(true)

  • 除上述值外的其它值类型与对象都转为 --> true
点击查看示例代码
console.log(!!{});
console.log(!![]);
console.log(!!new Date());
console.log(Boolean(1));
console.log(Boolean('123'));
1
2
3
4
5

# 数字Number

# 转换为number的方式

常用的两种

  • +value:以+开头
  • Number(value):用Number包裹

# 数组转数字

Array => Number

  • 空数组转为0: [] --> 0
  • 含有一个元素且为数字或数字字符串则转换为数字:[1]或['1'] --> 1
  • 其余情况转为NaN
点击查看示例代码
console.log(+[]); // 0
console.log(+[1]); // 1
console.log(Number(['1.23'])); // 1.23
console.log(Number([1,2])); // NaN
console.log(Number(['1',2])); // NaN
1
2
3
4
5

# 值类型转数字

  • null --> 0
  • '123' --> 123: 纯数字构成的字符串直接转换为应的数字
  • true --> 1
  • false --> 0
  • '124a' --> NaN
  • undefined --> NaN
  • Symbol --> 抛出错误
点击查看示例代码
console.log(+null); // 0
console.log(+undefined); // NaN
console.log(+'123'); // 123
console.log(+'true'); // NaN
console.log(+true); // 1
console.log(+false);// 0
1
2
3
4
5
6

# 引用类型转数字

除了上述的数组,日期(Date)之外的引用类型(Object)都转为NaN

点击查看示例代码
console.log(+ new Date()); // 1623597270652
console.log(+ [1]); // 1
console.log(+ {}); // NaN
console.log(+ /\d/); // NaN
1
2
3
4

# 字符串String

# 转字符串的方式

  • 加空字符串:’’ + value
  • String(value):用String包裹

# 值类型转字符串

  • 数字直接转
    • 666 --> '666':
  • 布尔值直接转换
    • true --> 'true'
    • false --> 'false'
点击查看示例代码
console.log(''+true); // 'true'
console.log(''+false); // 'false'
console.log(String(666)); // '666'
1
2
3

# 引用类型转数字

  • 数组
    • [] --> '' :空数组转为空串
    • [2,'3'] --> '2,3' :非空数组的每一项转为字符串再用,分割
  • 对象:
    • {} --> [object Object]
    • {a:1} --> [object Object]
点击查看示例代码
console.log(String([])); // ''
console.log(String([1,2,'3'])); // '1,2,3'
console.log(String({})); // '[object Object]'
console.log(String({a:1})); // '[object Object]'
1
2
3
4

# 对象转基础类型规则

对象在转换类型的时候,会调用内置的 [[ToPrimitive]] 函数,对于该函数来说,逻辑一般来说如下:

  1. 如果已经是基础类型了,那就不需要转换了
  2. 目标类型为字符串就先调用 toString
    • 转换为基础类型的话就返回转换的值
  3. 目标类型不为字符串就先调用 valueOf
    • 结果为基础类型,就返回转换的值
    • 结果不是基础类型的话再调用 toString
  4. 如果都没有返回基础类型,就会报错

各种情况示例如下:

点击查看示例代码
const demo1 = {
    [Symbol.toPrimitive]: function () {
        return 2
    }
}
// 情况1
console.log(demo1 + 1); // 3

const demo2 = {
    toString() {
        return 'demo2'
    },
    valueOf() {
        return 20
    }
}
// 情况2
console.log(String(demo2)) // demo2

// 情况3-1
console.log(demo2 - 3); // 17

const demo3 = {
    toString() {
        return 30
    },
    valueOf() {
        return {}
    }
}
// 情况3-2
console.log(demo3 - 4); // 26

const demo4 = {
    toString() {
        return {}
    },
    valueOf() {
        return {}
    }
}
// 情况4
console.log(demo4 + 1); // 报错
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

# 四则运算规则中的类型转换

# 加法

  • 有一方为String,那么另一方也会被转为String
  • 一方为Number,另一方为原始值类型,则将原始值类型转换为Number
  • 一方为Number,另一方为引用类型,双方都转为String
点击查看示例代码
'123' + 4 // '1234'

123 + true // 124
123 + undefined // NaN
123 + null // 123

123 + [] //  '123'
123 + {} // '123[object Object]'
1
2
3
4
5
6
7
8

# 其它

除了加法的运算符来说(-,*,/),会将非Number类型转换为Number类型

# 比较运算符中的类型转换

==

  1. NaN不等于任何其它类型
  2. Boolean 与其它类型进行比较,Boolean转换为Number
  3. String 与 Number进行比较,String 转化为Number
  4. null 与 undefined进行比较结果为true
  5. null,undefined与其它任何类型进行比较结果都为false
  6. 引用类型与值类型进行比较,引用类型先转换为值类型(调用[ToPrimitive])
  7. 引用类型与引用类型,直接判断是否指向同一对象

来源于参考资料中的网图

图片

点击查看示例代码
[]==![] // true
// [] == false  1. 根据运算符优先级 ![] --> false
// [] == 0      2. 上面规则2
// '' == 0      3. 上面规则6
//  0 == 0      4. 上面规则3
// 所以结果为true
1
2
3
4
5
6

# 自测

点击查看自测代码
if ([]) console.log(1);             
if ({}) console.log(2);             
if ([] == false) console.log(3);    
if ({} == false) console.log(4);    
if ([] == ![]) console.log(5);      
if ({} == !{}) console.log(6);      
if ('' == false) console.log(7);    
if (false == 0) console.log(8);     
if (1 == true) console.log(9);      
if ('' == 0) console.log(10);       
if (NaN == NaN) console.log(11);    
if ([] == !true) console.log(12);   
if ([] == false) console.log(13);   
if ([] == 0) console.log(14);       
if (+0 == -0) console.log(15);      
if (NaN == false) console.log(16);  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{ } +1              
1 + {}              
[] + 1              
1 + []              
[1, 2, 3] + 0       
[1, 2, 3] + '0'     
1 + '0'             
1 + 0               
1 + true            
1 + false           
'1' + true          
'1' + false         
![] + []            
1 - true            
'0' - 0             
0 - '1'             
false - true        
{ } -[]             
[] - {}             
false - []          
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# TODO

  • 补图:用图概括文章内容

参考

思否-前端碎碎念 之 为什么[] == ![] ? (opens new window)

freeCodeCamp-Javascript 隐式类型转换,一篇就够了 (opens new window)

Edit this page (opens new window)
Last Updated: 2022/5/15 12:46:34