资讯专栏INFORMATION COLUMN

Javascript中的类型转换

MobService / 2753人阅读

摘要:类型转换法则这里讨论里对不同类型进行运算的时候,是如何做类型转换的一般是隐式转换。转化过程先查看对象的方法是否返回基本类型。结果转为返回字符串。引用类型需先转换为基本类型。后记不同类型之间的类型转换,确实是让人挠头的语言。

Javascript为什么会有类型转换

Javascirpt世界里,不推荐大量的使用try...catch...,我想大概原因:

JS里任何类型之间的算数运算,逻辑运算和位运算都不会抛异常或者错误。例如 1/0 == Infinity, 0/0 = NaN, [ ] + 1 = "1" 等。所以catch到excepton/error的几率,相对于编译型语言甚至于python/ruby等动态语言,是大大地降低了。

try...catch...会在catch里转换到一个新的作用域,catch里面调用本函数或者函数外的对象时,增加了一层作用域的查找,降低了运行效率

如果有未知的风险,确实可以try...catch...。但是如果你的代码里有比较多的try...catch...,这就是bad smell,说明需要加强coding质量或者重构了。

类型转换法则

这里讨论JS里对不同类型进行运算的时候,是如何做类型转换的(一般是隐式转换)。

加法运算

1 + "-1" = "1-1"
基本类型之间相加时,只要其一是字符串,另外一个也会先转换为字符串,结果就变成字符串的连接。

[ ] + 1 = "1"
引用类型和基本类型相加。引用类型先转化为基本类型。转化过程:先查看对象的valueOf()方法是否返回基本类型。数组的valueOf返回它本身,属于object类型,不是基本类型。所以再调用toString方法。空数组[]的toString返回空字符串。结果转为‘’ + 1. 返回字符串‘1’。

[ ] + { } = [object Object]
引用类型之间的加法。引用类型需先转换为基本类型。 参考2,空数组[]转为空字符串。类似地空对象{ } 转换时,也先查看{ }.valueOf(). 因为 {}的valueof方法返回它自身,所以会调用{}.toString()返回‘[object Object]"。
这样结果变成 "" + "[object Object]" = "[object Object]"

1 + null = 1
因为已经是基本类型,而且没有字符串,所以会基于number类型运算。 null转为0, 结果是 1 + 0 = 1

1 + undefined = NaN
undefined 转为NaN, so 1+ NaN = NaN

false + null = 0
都是基本类型而且没有字符串,所以基于数字类型相加。 false转为0, null也为0. 结果 0 + 0 = 0

[1] + [2] = "12"
分别调用toString方法以转为基本类型,得到"1"和‘2’, "1" + "2" = "12"

加法以外的算数运算

加法以外的算数运算,如果有object类型(包括数组),先转为基本类型,这和加法运算是相同的。转换过程也是先查看valueOf是否返回基本类型,如果不是,就调用toString(这里假定toString都返回string。除非谁闲着没事,非得给一对象的toString返回对象类型?)

和加法运算不同的是,转换为基本类型后,所有的基本类型再转为number类型,最终以number类型进行运算。

1 - "-1" = "-1"
字符串“-1”转为number的-1, 结果1 - (-) = 2

[ ] - 1 = -1
[ ]先转为基本类型,是空字符。空字符再转为number为0 ,结果是0 - 1 = -1

[ ] / { }
空数组转为基本类型是空字符,空对象转为基本类型是[object Object],二者再分别转为数字类型是 0 和 NaN,最终结果为0/NaN = NaN

1 / null
都已经为基本类型,所以只要把null转为number类型的0, 然后1 / 0 = Infinity

1 * undefined
都已经为基本类型,所以只要把undefined转为number类型的NaN, 然后1 * NaN = NaN

逻辑运算

1 && null = null.
因为1 是真值,则返回第二个值, 即null

null && undefined = null
返回null,因为null是falsy,则返回第一个。

0 || {} = {}
返回 {}. 因为0 是falsy,返回第二个

1 || null = 1
返回1, 因为1是真值,返回第一个

位运算

~n = -(n+1)
例如~25 = -26. 这里是带符号的取反。如果是无符号的取反,结果就不一样了,有兴趣的可以在C语言里试试 ~25u

~null = -1
null转为0, ~0 = -(0+1) =-1

~undefined //SyntaxError: Invalid or unexpected token

~~23.5 = 23 ~~-23.5 = -23
但 Math.floor(-23.5) = -24. 故而一般用~~取整数位

If 运算

if(-1)if (-1 == true) 是不一样的。前者是真假判断: -1是truthy,是真值。后者类似算术运算:先转为number,true 转为1, 故而 -1 == 1是假值。

小结

这里总结了js类型转换和运行的基本规律,希望是可以满足基本的项目需要了。

后记

JS不同类型之间的类型转换,确实是让人挠头的语言。我猜想可能是JS产生的时候,web方兴未艾,web工程师的编程功底还没有很规范(至少没有今天这么多资料书籍和培训机构等),所以js允许类型转换,不同类型之间运算时,保证不抛异常或者尽量少抛。

但是现在前端和后端一样的庞大了,显然js的这样那样的技法往往会使工程师掉入陷阱。typescript应允而生,一个目的是也是帮助初级工程师写出还可以的代码(另外一个目的估计是降低后端开发者写前端的门槛和思维转变)。从这角度解读,ts也是为满足项目工程和公司的需要。如果想深入js学习,原生的js(es5/6)是绕不开的。

补证

前面提到“try...catch...会在catch里转换到一个新的作用域”,这是在《你不知道的JavaScript》中卷里看到的。后来感觉还是做些论证,否则老觉得不踏实。看如下代码:

function testException() {
    var error = "outer error"
    try {
        throw "inner error"
    } catch (error) {
        console.log(error)
        error = "modify inner error"
    }
    
    // 这里会输出 outer error(而不是modify inner error),
    // 说明catch...里修改的error,不是testExecution()函数作用域里的,而是一个“新”作用域里的error
    // 所以我们可认为,catch...创建了一个新的作用域。看来它和函数作用域的类似点,都接受“参数”
    console.log(error) 
}

testException()

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/83685.html

相关文章

  • JavaScript 中的强制类型转换

    摘要:完整清单是中添加,此处不予介绍布尔值用来表示可能是真或假的值。结果抽象比较运算符在比较它们之前在类型之间进行自动转换。中的隐式转换称为强制类型转换,并在规范中定义。这些内置类型可用于在不同类型之间进行显式转换。 翻译:疯狂的技术宅原文:https://www.valentinog.com/bl... 本文首发微信公众号:前端先锋欢迎关注,每天都给你推送新鲜的前端技术文章 show...

    endiat 评论0 收藏0
  • JavaScript 强制类型转换

    摘要:强制类型转换作为程序员,你一定获取过当前系统的时间戳。比如对于变量而言,此次强制类型转换是隐式的。然而则是非常典型的显式强制类型转换。隐式强制类型转换大部分被诟病的强制类型转换都是隐式强制类型转换。 JavaScript 强制类型转换 作为 JavaScript 程序员,你一定获取过当前系统的时间戳。在 ES5 引入 Date.now() 静态方法之前,下面这段代码你一定不会陌生: v...

    OnlyLing 评论0 收藏0
  • 聊一聊 JS 中的『隐式类型转换

    摘要:具体的行为取决于参数的类型。说到,就不得不提一下方法,方法自带隐式类型转换,该方法在测试其参数之前,会先调用方法将其转换为数字。全等运算符会先进行数据类型判断,并且不会发生隐式类型转换。 类型转换还不行?还非得隐式?这是什么高级玩意? 废话不多说,我们先上一盘?,额,不对,先看一个例子吧。 3 + true 实际上在大多数编程语言中,都会认为上面这个表达式是错误的。因为布尔表达式与算术...

    Jenny_Tong 评论0 收藏0
  • JavaScript类型转换与各种运算符

    摘要:第十七天笔记类型转换隐式类型转换隐式类型转换是弱类型松散类型的在任何情况下都可以强制转换定义类型类型以及类型的变量卧龙前端转换为类型转换为类型类型转换为类型如果文本内容是普通的文本非数字转换后的结果为如果文本内容是数字值转换后的结果为对 第十七天笔记 类型转换 隐式类型转换 隐式类型转换 JavaScript是弱类型/松散类型的 在任何情况下都可以强制转换 //定义number类型 s...

    Aklman 评论0 收藏0
  • 简单说 JavaScript中的tostring( ) 与 valueOf( )方法

    摘要:日期类定义的方法会返回它的一个内部表示年月日以来的毫秒数。和应用的对象到原始值的转换包含日期对象的一种特殊情形。简单说与引发的思考简单说通过的隐式转换,关键时刻救你一命 说明 所有的对象都继承有toString() 和 valueOf() 方法,对象到字符串,对象到数字的转换,会通过调用待转换对象的这两个方法中的一个来完成。 解释 toString( )方法的作用是: 返回一个反映这个...

    ztyzz 评论0 收藏0
  • 简单说 JavaScript中的tostring( ) 与 valueOf( )方法

    摘要:日期类定义的方法会返回它的一个内部表示年月日以来的毫秒数。和应用的对象到原始值的转换包含日期对象的一种特殊情形。简单说与引发的思考简单说通过的隐式转换,关键时刻救你一命 说明 所有的对象都继承有toString() 和 valueOf() 方法,对象到字符串,对象到数字的转换,会通过调用待转换对象的这两个方法中的一个来完成。 解释 toString( )方法的作用是: 返回一个反映这个...

    tain335 评论0 收藏0

发表评论

0条评论

MobService

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<