原文:JavaScript quirk 1: implicit conversion of values

译文:「译」JavaScript 的怪癖 1:隐式类型转换

译者:justjavac


零:提要

[此贴子是 javascript 的 12 个怪癖(quirks) 系列的第一篇。]

JavaScript 是非常宽容的,「来者不拒」,不在乎什么类型。 例如,它如果想要接受数字,它并不拒绝其他类型的值,而是试图把它们转换成数字:

> '5' - '2'
3
> '5' * '2'
10

自动转换为布尔值通常不会引起问题,而且往往很有用(译注:比如在C语言里,根本就没有布尔类型。by @justjavac)。 即使如此,这些隐式转换也会引起怪癖(quirks)。 但是当自动转换为字符串时,可能会引起问题。

一:隐式转换为布尔:“truthy”和“falsy”

当 JavaScript 需要一个布尔值时(例如:if 语句),任何值都可以被使用。 最终这些值将被转换为 true 或false

下面的值被转换为 false

  • undefined, null
  • Boolean: false
  • Number: -0, +0, NaN
  • String: ''

所有其他值都认为是 true。 被转换成 'false' 的值我们成之为 falsy,被转换成 'true' 的值我们成之为 truthy。 您可以使用 Boolean 来测试一个值到底被转换成了什么。

Boolean 将其参数转换为布尔值(boolean):

> Boolean(undefined)
false
> Boolean(0)
false
> Boolean(3)
true

二、字符串的隐式转换

在 Web 开发中,我们经常得到字符串值,实际上我们期望的却是数字或者布尔值。 例如,用户输入的表单中的数据。 如果你忘了对这些字符串进行显式的转换,那么 JavaScript 会令你感到惊讶,主要体现在两个方面:

  1. 首先,系统不会有任何警告。
  2. 其次,这些值将被自动转换,但确实错误的。

例如,加运算符(+),就有这方面的问题,因为只要其中一个操作数是字符串,那么它就执行连接字符串的操作(而不是加法操作,即使它们是数字)

在下面的 JavaScript 代码中,我们本来预期是把 1 和 5 相加。 但是,我们使用了字符串 '5' 和 '1' 。

> var x = '5';  // 错误的假设:x 是一个数字

> x + 1
'51'

此外,还有一些看似是 false 的值,如果转换成字符串,却成了 'true'。

例如:false

> Boolean(false)
false
> String(false)
'false'
> Boolean('false') // !!
true

例如: undefined.

> Boolean(undefined)
false
> String(undefined)
'undefined'
> Boolean('undefined') // !!
true

三、对象的隐式转换

只有在 JavaScript 表达式或语句中需要用到数字或字符串时,对象才被隐式转换。 当需要将对象转换成数字时,需要以下三个步骤:

  1. 调用 valueOf()。如果结果是原始值(不是一个对象),则将其转换为一个数字。
  2. 否则,调用 toString() 方法。如果结果是原始值,则将其转换为一个数字。
  3. 否则,抛出一个类型错误。

第一步示例:

> 3 * { valueOf: function () { return 5 } }
15

第三步示例:

> function returnObject() { return {} }
> 3 * { valueOf: returnObject, toString: returnObject }
TypeError: Cannot convert object to primitive value

如果把对象转换成字符串时,则转换操作的第一步和第二步的顺序会调换: 先尝试 toString() 进行转换,如果不是原始值,则再尝试使用 valueOf()

「译」JavaScript 的怪癖 1:隐式类型转换的更多相关文章

  1. iOS 9,为前端世界都带来了些什么?「译」 - 高棋的博客

    2015 年 9 月,Apple 重磅发布了全新的 iPhone 6s/6s Plus.iPad Pro 与全新的操作系统 watchOS 2 与 tvOS 9(是的,这货居然是第 9 版),加上已经 ...

  2. 「译」JUnit 5 系列:条件测试

    原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...

  3. 「译」JUnit 5 系列:扩展模型(Extension Model)

    原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...

  4. jvm系列(十):如何优化Java GC「译」

    本文由CrowHawk翻译,是Java GC调优的经典佳作. 本文翻译自Sangmin Lee发表在Cubrid上的"Become a Java GC Expert"系列文章的第三 ...

  5. jvm系列(七):如何优化Java GC「译」

    本文由CrowHawk翻译,地址:如何优化Java GC「译」,是Java GC调优的经典佳作. Sangmin Lee发表在Cubrid上的”Become a Java GC Expert”系列文章 ...

  6. 有趣的JavaScript隐式类型转换

    JavaScript的数据类型是非常弱的(不然不会叫它做弱类型语言了)!在使用算术运算符时,运算符两边的数据类型可以是任意的,比如,一个字符串可以和数字相加.之所以不同的数据类型之间可以做运算,是因为 ...

  7. JavaScript 隐式类型转换

    JavaScript 隐式类型转换 原文:https://blog.csdn.net/itcast_cn/article/details/82887895 · 1.1 隐式转换介绍 · 1.2 隐式转 ...

  8. JavaScript学习总结(二、隐式类型转换、eval())

    一.(避免)隐式类型转换 console.log(false == 0);   //logs true; console.log(false === 0);   //logs false; conso ...

  9. Javascript显示和隐式类型转换

    1.转换成字符串 多数的JavaScript宿主环境(比如Node.js和Chrome)都提供了全局函数toString: 与此同时Object.prototype也定义了toString方法,使得所 ...

随机推荐

  1. A woman without arms

    任吉美出生在中国烟台海阳一个极为普通的渔民家里.她先天残疾,没有胳膊和手. 小吉美注定要比别人生活得更艰难.她不能自己穿衣,不能自己端碗吃饭,也不能像兄弟姐妹们一样帮助妈妈干家务活,她觉得自己成了家里 ...

  2. yii中设置提示成功信息,错误提示信息,警告信息

    方法一: <?phpYii::app()->user->setFlash(‘success’,”Data saved!”); 设置键值名为success的临时信息.在getFlash ...

  3. 多种css3时尚侧栏菜单展开显示效果Off-Canvas Menu Effects

    今天我们想分享多种css3时尚侧栏菜单展开显示效果.侧边栏应用广泛,我们之前已经产生了一些效果灵感.风格演变,今天我们要展示一套新的灵感的现代效果.不同的布局和菜单的同步转换和页面可以让一切看起来更有 ...

  4. bjfu1262 优先队列

    比较典型的应用优先队列的题.题目是在一个长为n的数组中,依次问m个数中的最小值.那么把值和下标做成一个结构体,放进优先队列里,每次移动窗口就把该T的T掉,剩下的最小值就是答案,复杂度nlogn,轻松a ...

  5. 性能测试指标&说明 [解释的灰常清楚哦!!]

    详见: 浅谈软件性能测试中关键指标的监控与分析 http://www.51testing.com/html/18/n-3549018.html

  6. VBS学习:流程控制语句判断结构

    一.数值运算: 1) Dim a,b,c a=inputbox("a是:","输入半径") b=Inputbox("b是:","输 ...

  7. C++的类成员和类成员函数指针

    类成员函数指针: 用于访问类成员函数,和一般函数指针有区别. 类成员函数处理的是类数据成员,声明类成员函数指针的同时,还要指出具体是哪个类的函数指针才可以.调用时也要通过对象调用. 而对于类的静态成员 ...

  8. 用Python组合Celery Redis RabbitMQ进行分布式数据抓取

    首先,记录下遇到的问题吧,在抓取的过程中为了避免IO操作,主要用Redis做插入缓存,当内存占用率很大时,会周期性的持续到Mysql里 虽然是拆东墙补西墙,但把数据抓取完毕后持续化可以慢慢进行,毕竟数 ...

  9. Redis批量导入数据

    首先准备数据文件 格式为 SET Key0 Value0 SET Key1 Value1 ... SET KeyN ValueN 利用shell转换数据 #!/bin/bash while read ...

  10. windows分屏

    一.准备 主机.显示屏A.显示屏B.DVI连接线2根 二.操作步骤 1.使用DVI连接线将显示屏A连接到主机上,开机进入windows系统(演示用的是win 7)(若已连接,请跳到第2步.基本上这一步 ...