捉摸不透的女生——JavaScript类型转换

起因

凡事都有个来源和起因,这个题不是我在哪篇文章看到的,也不是我瞎乱造出来的,是在看一个重学 Js 类型转换视频中老师使用console.log({} + []) 在控制台输出了[object Object],不过看了人家的视频自己也需要动手敲一下嘛,于是我没有在编辑器里边编辑,偷了个懒直接在控制台里边编辑打印。巧了 竟然返回结果不一样!!

ZN3qi9.png

对结果出乎意料,本着实事求是的精神,探寻事物的本质,不断努力追根溯源,总算明白了最后的结果,最后的收获总算把 js 的隐式类型转换刨根问底的搞清楚了,也更加深入的明白了为什么 Js 是弱类型语言了。

开胃小菜

Number({1:2})
[] + {}
[] + function() {}
2 + [2,3]
10 + function() {}
null + undefined
[] - 5
'6' * []
null % true
true/[7]
"A" - "A" + 2

答案

Js 数据类型(6 种)

Javascript 有两种数据类型,分别是基本数据类型引用数据类型。其中基本数据类型包括 UndefinedNullBooleanNumberStringSymbol (ES6 新增,表示独一无二的值),而引用数据类型统称为 Object 对象,主要包括对象、数组和函数。

这里抛开 Symbol 不论述

在 js 中可以把任意一种数据类型转换为数字字符串*、*布尔值

在运行true + 12时 Js 并不会报错,由于 Js 是一种弱类型语言,Js 会自动转换,将其输出。 看到这是不是觉得 Js 编译很贴心(暖暖的),但是呢,有利就有弊,有的时候也就是因为它会自动转换类型,会出现你意想不到的结果。

数据类型转换分为显式和隐式

Number()显式

总结

    1. undefined–>>NaN

    2. null————>>0

    3. 布尔值——–true 为 1,false 为 0

    4. 字符串

      1. 空字符串、空格字符串转为 0

      2. 非空字符串,并且内容为纯数字(包含进制与科学计数法)转对应的数字

      3. 其余都是NaN

    5. 数字 原来的数字

    6. 对象

      1. 对象 函数转 NaN

      2. 空数组转为 0,数组里只有一个数据并且这个数据能转为数字,则转为对应的数字,其他都转成NaN

String()显式

总结

    1. 基本数据类型nullundefined 的结果就是给数据加上引号变成字符串

    2. 对象

      1. 数组的结果为把所有的中括号去掉,然后在外面加个引号

      2. 对象的结果为”[object Object]“(除了日期对象)

      3. 函数的结果为在函数整体外面加个引号

Boolean()显式

总结

  • Boolean()

    1. undefined——>>false

    2. null———–>>false

    3. 数字

      • +0-0NaN转布尔值的结果为false,其他的转布尔值结果为true

    4. 布尔值 转为对应的值

    5. 字符串

      • 空字符串转布尔值为false,其他(包括空格字符串)的都转为true

    6. 对象转布尔值都是true

答案

原理

对象的原型上都有一个 toString()和 valueOf()方法

  • toString()

    • 返回对象的字符串表现形式

  • valueOf()

    • 返回对象对应的数值

  • 数字、字符串、布尔值

    • valueOf—-数据本身(原始值形式)

    • toString—-数据转换为字符串的形式

  • 数组

    • valueOf—-数据本身(对象形式)

    • toString—-去掉中括号,外面加个引号(本质为调用 join(",")后的结果)

  • 函数

    • valueOf—-数据本身(对象式)

    • toString—-在数据外面加个引号

  • 对象

    • valueOf—-数据本身(对象形式)

    • toString—-“[object Object]

Number 参数为对象的转换原理

  1. 调用对象的valueOf方法,如果返回原始类型的值,再使用Number函数,不在进行后续步骤

  2. 如果valueOf方法返回的还是对象,则调用toString方法

  3. 如果toString方法返回原始类型的值,则对该值使用Number方法,不进行后续步骤

  4. 如果toString方法后返回的还是对象,就报错(一般不会出现)

String 参数为对象的转换原理

  1. 调用对象的toString方法,如果返回原始类型的值,再使用String函数,不在进行后续步骤

  2. 如果toString方法返回的还是对象,则调用valueOf方法

  3. 如果valueOf方法返回原始类型的值,则对该值使用String方法,不进行后续步骤

  4. 如果valueOf方法后返回的还是对象,就报错(一般不会出现)

隐式转换

出现的场景

  1. 不同类型的数据间运算,比较

  2. 对费布尔值类型的数据求布尔值

  3. 条件语句的括号里

隐式类型转数字

出现的场景

+ - * / % 加号+运算符里不能出现字符串或对象类型 + -(正负) 某些比较运算符

去看 Number 显式转换

隐式类型转字符串

去看 String 显式转换

出现场景

  1. 有字符串的加法运算

  2. 有对象的加法运算

  3. 某些比较运算符

  4. 调用 alert、document.write 方法

来看看下面这道题输出的结果是什么吧(注意过程)

隐式类型转布尔值

去看 Boolean 显式转换

出现场景

  1. 取反运算

  2. 1 个叹号表示,把这个数据转换成布尔值后取它的反值

  3. 2 个叹号表示,把这个数值转成布尔值

  4. 三目运算符

  5. 条件语句的小括号里

  6. 逻辑运算符

大小比较的原理

  1. 如果比较两边有字符串,那会对比他们各自对应的 Unicode 码值

  2. 如果两边都为原始类型数据,都把所有数据转成数字进行比较,NaN 与任何数据对比都是 false

  3. 有对象数据的比较,先调用 valueOf 再调用 toString 方法,然后看另一数据的类型,如果另一数据为字符串,则转为字符串对比,如果另一数据为数字,则转为数字对比。

总结

  1. 字符串与字符串,字符串与对象,对象与对象进行比较时,都会转成字符串,然后对比 Unicode 码值

  2. 其他类型数值,转成数字对比

相等比较原理

  1. 不同类型的原始类型数据,把所有的数据转成数字后进行对比

  2. null 和 undefined 除了它们自己与自己,自己与对方相等,与其他任何数据都不相等

  3. 对象与原始类型比较时,把对象转换成原始值,在进行比较

  4. 对象与对象类型比较时,比较的是他们的引用地址,除非引用地址相同,否则都不相等

总结

  • 原始类型对比,转成数字对比

  • 对象类型对比,把对象转成字符串,然后看对方的类型

    • 如果不一样,都转成数字对比

    • 对象与对象比较,比较引用地址

    • 自己与自己,自己与对方相等

    • 与其他任何数据都不相等

逻辑运算符

&&: 两边的数据必须要都成立,整个表达式才能成立

||: 有一方成立,整个表达式成立

总结

  • && (找

    )

    • 左边为真的话,直到找到为 false 结果的值返回

    • 左边不为真,直接返回左边表达式的值

  • || (找

    )

    • 左边不为真的话,直到找到为 true 结果的值返回

    • 左边为真,直接返回左边表达式的值

逗号运算符

小逗号,大用处

总结

  1. 逗号运算符可以从左往右依次执行表达式

  2. 最后的那个表达式结果返回

  3. 优先级最低

  4. alert 只能接收一个参数

面试题分享,请将下面的 a 返回 20,b 返回 10

我们在这里可以想到很多方法,比如增加一个中间值,相加相减,ES6 的解构赋值等。这里,我们可以使用逗号','运算符巧妙解决这个问题。

a=[b][b=a,0] 这样就可以完美的解决了此问题

我们继续

最后更新于