- 原文地址:2ality.com/2013/04/qui…
- 原文做者:Dr. Axel Rauschmayer
- Markdown 地址:github.com/Yangfan2016…
- 译者:Yangfan2016
JavaScript 是对值的接受是很是宽松的。例如在任何期待一个 number 类型的值的地方,它不会拒绝来自其余类型的值,而是会试图转换它们:html
> '5' - '2'
3
> '5' * '2'
10
复制代码
自动转换成 boolean 值是不多出问题而且颇有用。这里先埋下个伏笔(咱们将用它解决一些怪异问题)。然而,自动转换为 string 可能会形成一些问题git
无论什么时候 JavaScript 接受一个 boolean 值时(例如,if 语句的条件),任何值均可以用。它要么解释为 true,要么解释为 false。下面的值都会被解释为 false:github
undefined, null
Boolean: false
Number: -0, +0, NaN
String: ''
复制代码
其余全部的值都会被看成 true。值被解释为 false 的称做 falsy(假值),值被解释为 true 的称做 truthy(真值)。你可使用 Boolean 函数来测试一个值会被解释为何。它会把它的参数转换为 boolean 值:web
> Boolean(undefined)
false
> Boolean(0)
false
> Boolean(3)
true
复制代码
在 web 开发中,你会常常获取到其实是 number 或 boolean 而看成 string 类型的值。例如,当用户在表单输入一些数据时。若是你忘记了显式转换这些 string 的话,JavaScript 会给你带来两个消极方面的惊喜:首先,不会有任何警告。其次,值会被自动转换,可是是错的。例如,操做符加号(+)就有问题,由于只要操做符的一边是 string 类型的,它就会当成字符串链接符。在下面的例子中,假设咱们执行的是 1 和 5 相加,而实际上,咱们执行的是 ‘1’ 和 ‘5’ 字符串链接app
> var x = '5'; // 错误假设:x 是 number 类型
> x + 1
'51'
复制代码
此外,还有一些极少数的 falsy 值,若是被转换为 string 类型的,就会被当成 truthy,例如:false函数
> Boolean(false) // truthy?
false
> String(false)
'false'
> Boolean('false') // truthy?
true
复制代码
例如:undefined测试
> Boolean(undefined) // truthy?
false
> String(undefined)
'undefined'
> Boolean('undefined') // truthy?
true
复制代码
若是 JavaScript 期待的是 number 或 string 类型的值的时候,object 才会发生隐式转换。第一种状况下(期待 number),会按照三个步骤进行转换:ui
译者改:spa
译者注:这里注意 Date 对象(object)特殊,valueOf 和 toString 调用顺序不一样翻译
第 1 步的例子:
> 3 * { valueOf: function () { return 5 } }
15
复制代码
第 3 步的例子:
> function returnObject() { return {} }
> 3 * { valueOf: returnObject, toString: returnObject }
TypeError: 没法将 object 转换为原始类型
复制代码
若是是 JavaScript 转换为 string 类型,那步骤 1 和步骤 2 进行交换:首先试图调用 toString() 方法,而后调用 valueOf() 方法
最好的办法是在使用它们以前就显式转换为指望的类型。一个迷你的解决方案是用 Boolean(),Number() 和 String() 方法:
function handleFormData(formData) {
var givenName = String(formData.givenName);
var age = Number(formData.age);
...
}
复制代码
这些函数总会返回一个值(它们永远都不会抛出异常)。然而 Number() 函数在它不能转换一个值时会返回 NaN
[1]:
> Number('xyz')
NaN
> Number(undefined)
NaN
> Number(null)
0
> Number(true)
1
复制代码
更详细的解决方案是在你转换这些值时,先检查下它们的格式(例如,人们不能把 ‘xyz’ 做为它们的年龄),若是不对,要采起适当的解决措施
感谢@hsy0 的评论,原文做者这里没有讲清楚,毕竟一千我的一千个哈姆雷特,咱们仍是直接看标准吧 ecma-262/6.0/#sec-toprimitive
其实真实转换过程以下(做者在另外一篇文章中提到了,😂,和标准一致),就不翻译了
An object obj is converted to a number by calling ToPrimitive(obj, Number) and then applying ToNumber() to the (primitive) result. An object obj is converted to a number by calling ToPrimitive(obj, String) and then applying ToString() to the (primitive) result.