JavaScript类型转换总结与常见情况分析

类型转换是将值从一种类型转换为另一种类型的过程(比如字符串转数字,对象转布尔值等)

一、类型转换的分类

类型转换可以分为隐式类型转换和显式类型转换。

二者的区别显而易见:我们能够从代码中看出哪些地方是显式强制类型转换,而隐式强制类型转换则不那么明显,通常是某些操作产生的副作用。

例如:

var a = 42;

var b = a + "";       // 隐式强制类型转换

var c = String( a );  // 显式强制类型转换

对变量 b 而言,强制类型转换是隐式的;由于 + 运算符的其中一个操作数是字符串,所以是字符串拼接操作,结果是数字 42 被强制类型转换为相应的字符串”42“。

而 String() 则是将 a 显示强制类型转换为字符串。

严格相等运算符(===)不会触发类型隐式转换,所以它可以用来比较值和类型是否都相等。

隐式类型转换是一把双刃剑,使用它虽然可以写更少的代码但有时候会出现难以被发现的bug。

二、三种类型转换

1、Boolean 类型转换

在条件判断时,除了 undefined,null,false,NaN,‘ ‘,0,-0,其它所有值都转为 true,包括所有对象。

Boolean() 方法可以用来显式将值转换成 boolean 型。

隐式类型转换通常在逻辑判断或者有逻辑运算符时被触发(|| && !)

Boolean(2)     // 显示类型转换
if(2) {}          // 逻辑判断触发隐式类型转换
!!2                 // 逻辑运算符触发隐式类型转换
2 || ‘hello‘      // 逻辑运算符触发隐式类型转换

2、String 类型转换

String() 方法可以用来显式将值转为字符串,隐式转换通常在有 + 运算符并且有一个操作数是 string 类型时被触发,如:

String(123) // 显式类型转换

123 + ‘‘      // 隐式类型转换

Symbol 类型转 String 类型是比较严格的,它只能被显式的转换

String(Symbol(‘symbol‘))  // ‘Symbol(symbol)‘

‘‘ + Symbol(‘symbol‘)       // TypeError is thrown

3、Number 类型转换

和 Boolean()、String() 方法一样, Number() 方法可以用来显式将值转换成 number 类型。

number 的隐式类型转换是比较复杂的,因为它可以在下面多种情况下被触发。

  • 比较操作(>, <, <=, >=)
  • 按位操作(| & ^ ~)
  • 算数操作(- + * / %)--- 注意:当 + 操作存在任意的操作数是 string 类型时,不会触发 number 类型的隐式转换
  • 一 元 + 操作
  • 非严格相等操作(== 或者 !== )--- 注意:== 操作两个操作数都是 string 类型时,不会发生 number 类型的隐式转换
Number(‘123‘)    // 显示类型转换
+ ‘123‘              //  隐式类型转换
123 != "456"     //  隐式类型转换
4 > "5"             //  隐式类型转换
5 / null             //  隐式类型转换
true | 0            //  隐式类型转换

这里有 2 个特殊的规则需要记住:

  • 当将 == 应用于 null 或 undefined 时,不会发生数值转换。null 只等于 null 或 undefined,不等于其他任何值。
null == 0                       // false, null is not converted to 0
null == null                    // true
undefined == undefined  // true
null == undefined           // true
undefined == 0              // false
  • NaN 不等于任何值,包括它本身
NaN === NaN      // false

4、object 类型转换

到这里我们已经深入了解了原始类型的转换,接下来我们来看一下对象转原始类型。

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

  • 如果已经是原始类型了,那就不需要转换了
  • 如果需要转字符串类型就调用 x.toString(),结果为基础类型则返回转换的值;非字符串类型则先调用 valueOf,结果非基础类型再调用 toString
  • 调用 x.valueOf() ,如果转换为基础类型,则返回转换的值
  • 如果都没有返回原始类型,就会报错

当然也可以重写 Symbol.toPrimitive,该方法在转原始类型时调用优先级最高:

let a = {
  valueOf() {
    return 0
  },
  toString() {
    return ‘1‘
  },
  [Symbol.toPrimitive]() {
    return 2
  }
}
1 + a     // => 3

5、四则运算符

加法运算符不同于其他几个运算符,它有以下两个特点:

  • 特点一:运算中其中一方为字符串,那么就会把另一方也转换为字符串
  • 特点二:如果一方不是字符串或者数字,那么会将它转换为数字或者字符串
1 + ‘1‘            // ‘11‘
true + true     // 2
4 + [1,2,3]    // "41,2,3"

如果你对于答案有疑问的话,请看解析:

  • 对于第一行代码来说,触发特点一,所以将数字 1 转换为字符串,得到结果 ‘11‘
  • 对于第二行代码来说,触发特点二,所以将 true 转为数字 1
  • 对于第三行代码来说,触发特点二,所以将数组通过 toString 转为字符串 1,2,3,得到结果 41,2,3

另外对于加法还需要注意这个表达式 ‘a‘ + + ‘b‘

‘a‘ + + ‘b‘     // -> "aNaN"

因为 + ‘b‘ 等于 NaN,所以结果为 "aNaN",你可能也会在一些代码中看到过 + ‘1‘ 的形式来快速获取 number 类型。

那么对于除了加法的运算符来说,只要其中一方是数字,那么另一方就会被转为数字

4 * ‘3‘         // 12
4 * []         // 0
4 * [1, 2]   // NaN

6、比较运算符

  • 如果是对象,就通过 toPrimitive 转换对象
  • 如果是字符串,就通过 unicode 字符索引来比较
let a = {
  valueOf() {
    return 0
  },
  toString() {
    return ‘1‘
  }
}
a > -1     // true

在以上代码中,因为 a 是对象,所以会通过 valueOf 转换为原始类型再比较值。

三、18 种常见情况解析

1、常见情况

true + false     // 1

‘+‘ 运算符会触发 number 类型转换对于 true 和 false

2、常见情况

12 / ‘6‘     // 2

算数运算符会把字符串 ‘6’ 转为 number 类型

3、常见情况

"number" + 15 + 3        // "number153"

‘+‘ 运算符按从左到右的顺序的执行,所以优先执行 “number” + 15, 把 15 转为 string 类型,得到 “number15” 然后同理执行 “number15” + 3

4、常见情况

15 + 3 + "number"     // "18number"

15 + 3 先执行,运算符两边都是 number 类型 ,不用转换,然后执行 18 + “number” 最终得到 “18number”

5、常见情况

[1] > null  // true

==> ‘1‘ > 0
==> 1 > 0
==> true

比较运算符 > 执行 number 类型隐式转换。

6、常见情况

"foo" + + "bar"  // "fooNaN"

==> "foo" + (+"bar")
==> "foo" + NaN
==> "fooNaN"

一元 + 运算符比二元 + 运算符具有更高的优先级。所以 + bar表达式先求值。一元加号执行字符串“bar” 的 number 类型转换。因为字符串不代表一个有效的数字,所以结果是NaN。在第二步中,计算表达式‘foo‘ + NaN

7/8、常见情况

‘true‘ == true       // false

==> NaN == 1
==> false

‘false‘ == false     // false

==> NaN == 0
==> false

== 运算符执行 number 类型转换,‘true‘ 转换为 NaN, boolean 类型 true 转换为 1

9、常见情况

null == ‘‘ // false

null 不等于任何值除了 null 和 undefined

10、常见情况

!!"false" == !!"true"  // true

==> true == true
==> true

!! 运算符将字符串 ‘true‘ 和 ‘false‘ 转为 boolean 类型 true, 因为不是空字符串,然后两边都是 boolean 型不在执行隐式转换操作。

11、常见情况

[‘x‘] == ‘x‘     // true

== 运算符对数组类型执行 number 转换,先调用对象的 valueOf() 方法,结果是数组本身,不是原始类型值,所以执行对象的 toString() 方法,得到字符串 ‘x‘

12、常见情况

[] + null + 1      // ‘null1‘

==> ‘‘ + null + 1
==> ‘null‘ + 1
==> ‘null1‘

‘+‘ 运算符执行 number 类型转换,先调用对象的 valueOf() 方法,结果是数组本身,不是原始类型值,所以执行对象的 toString() 方法,得到字符串 ‘‘, 接下来执行表达式 ‘‘ + null + 1

13、常见情况

0 || "0" && {}      // {}

==> (0 || ‘0‘) && {}
==> (false || true) && true
==> true && true
==> true

逻辑运算符 || 和 && 将值转为 boolean 型,但是会返回原始值(不是 boolean)

14、常见情况

[1,2,3] == [1,2,3]     // false

当运算符两边类型相同时,不会执行类型转换,两个数组的内存地址不一样,所以返回 false

15、常见情况

{} + [] + {} + [1]      // ‘0[object Object]1‘

==> +[] + {} + [1]
==> 0 + {} + [1]
==> 0 + ‘[object Object]‘ + ‘1‘
==> ‘0[object Object]1‘

所有的操作数都不是原始类型,所以会按照从左到右的顺序执行 number 类型的隐式转换, object 和 array 类型的 valueOf() 方法返回它们本身,所以直接忽略,执行 toString() 方法。 这里的技巧是,第一个 {} 不被视为 object,而是块声明语句,因此它被忽略。计算从 +[] 表达式开始,该表达式通过toString()方法转换为空字符串,然后转换为0

16、常见情况

! + [] + [] + ![]     // ‘truefalse‘

==> !(+[]) + [] + (![])
==> !0 + [] + false
==> true + [] + false
==> true + ‘‘ + false
==> ‘truefalse‘

一元运算符优先执行,+[] 转为 number 类型 0,![] 转为 boolean 型 false

17、常见情况

new Date(0) - 0      // 0

==> 0 - 0
==> 0

‘-‘ 运算符执行 number 类型隐式转换对于 Date 型的值,Date.valueOf() 返回到毫秒的时间戳

18、常见情况

new Date(0) + 0

==> ‘Thu Jan 01 1970 02:00:00 GMT+0200 (EET)‘ + 0
==> ‘Thu Jan 01 1970 02:00:00 GMT+0200 (EET)0‘

‘+‘ 运算符触发默认转换,因此使用 toString() 方法,而不是 valueOf()

原文地址:https://www.cnblogs.com/Leophen/p/11384511.html

时间: 2024-10-11 15:54:12

JavaScript类型转换总结与常见情况分析的相关文章

AWR收集缓慢、挂起的几种常见情况分析

AWR(Automatic Workload Repository)作为对数据库性能诊断的工具,采集与性能相关的统计数据,根据这些统计数据中的性能指标,以跟踪潜在的问题.若因某些情况导致相关数据无法收集,就会对数据库性能诊断大打折扣. 以下列举AWR收集缓慢.挂起或缺失常见的几种情况: STATISTICS_LEVEL 参数不为ALL或TYPICAL SYSAUX表空间不足 系统资源I/O.CPU使用率过高 MMON/MMNL进程异常 相关FIXED TABLE统计信息不准确 STATISTIC

对null,undefined取反的常见情况分析

1.对空数组判断 var aa=[]; if(aa){ //此时aa为真,所以继续执行 console.log(23423); } 2.对字面量声明的空对象判断 var bb = {}; if(bb){ //此时bb为真,继续执行 alert(234); } 3.对null对象判断 var cc=null; if(!cc){ // 此时cc为假,取反为真,继续执行 alert(34); } 4.对undefined判断 var dd = undefined; if(!dd){ // 此时dd为假

Javascript语言精粹之String常用方法分析

Javascript语言精粹之String常用方法分析 1. String常用方法分析 1.1 String.prototype.slice() slice(start,end)方法复制string的一部分来构造一个新的字符串 start<0时,它将于string.length相加 end参数可选,默认值为string.length.如果end<0,它将于string.length相加 var text='and in it he say " Any damn fool could'

移动站Web开发图片自适应两种常见情况解决方案

本文主要说的是Web中图片根据手机屏幕大小自适应居中显示,图片自适应两种常见情况解决方案.开始吧 在做配合手机客户端的Web wap页面时,发现文章对图片显示的需求有两种特别重要的情况,一是对于图集,这种文章只需要左右滑动浏览,最好的体验是让图片缩放显示在屏幕有效范围内,防止图片太大导致用户需要滑动手指移动图片来查看这种费力气的事情,用户体验大大降低.二是图文混排的文章,图片最大宽度不超过屏幕宽度,高度可以auto.这两种情况在项目中很常见.另外,有人说做个图片切割工具,把图片尺寸比例都设定为统

.Net 内存溢出(System.OutOfMemoryException)的常见情况和处理方式总结

.Net 内存溢出(System.OutOfMemoryException)的常见情况和处理方式总结 在什么情况下会出现OutOfMemonryException呢? 在我们试图新建一个对象时,而垃圾收集器又找不到任何可用内存时被抛出,这种情况下我们是可以捕获该异常的; 另一种情况是,CLR需要内存时,而却系统却不能提供,也会抛出该异常. 但此时,我们的应用程序是不能捕获该错误的. 内存溢出(OutOfMemoryException)的调试分析 32位操作系统的寻址空间是4G,其中有2G被操作系

Javascript中的attribute和property分析

attribute和property这两个单词,都有属性的意思,attribute有属性.特质的意思,property则有性质,性能的意思. 首先需要明确的是,在规范中,读取和设置attribute的方法是getAttribute/setAttribute/removeAttribute,比如box.setAttribute('somekey','somevalue') 而想要访问元素的property,则需要用.(点)的方法,比如,box.somekey,下面先说attribute: <div

javascript类型转换

Javascript类型转换: 值 转换为:字符串 数字 布尔值 对象 undefined "undefined" NaN false throws TypeError null "null" 0 false throws TypeError true "true" 1 new Boolean(true) false "false" 0 new Boolean(false) ""空字符串 0 false n

复旦大学2015--2016学年第二学期高等代数II期末考试情况分析

一.期末考试成绩班级前几名 胡晓波(90).杨彦婷(88).宋卓卿(85).唐指朝(84).陈建兵(83).宋沛颖(82).王昊越(81).白睿(80).韩沅伯(80).王艺楷(80).张漠林(80).张子涵(80) 二.总成绩计算方法 平时成绩根据交作业的次数决定,本学期共交作业12次,10次以上(包括10次)100分,少一次扣10分. 总成绩=平时成绩*20%+期中考试成绩*20%+期末考试成绩*60% 三.最终成绩及人数 最终成绩 人数 A 26 A- 1 B+ 14 B 16 B- 20

javascript 类型转换

JavaScript任何时候都可以为变量赋值(数字.字符串等),不过如果我让两个变量相加,其中一个是数字,另一个是字符串,会发生什么呢? JavaScript很聪明,它会尝试根据你的需要转换类型.例如,如果你将一个字符串和一个数字相加,它就会把这个数字转换为一个字符串,然后将两个字符串串联起来.这就是这篇文章要讲的JavaScript类型转换, 介绍: JavaScript中变量可以分配到Reference value或者Primitive Value.Reference value也称为对象,