JavaScript 中的强制类型转换

翻译:疯狂的技术宅
原文: https://www.valentinog.com/bl...

本文首发微信公众号:前端先锋
欢迎关注,天天都给你推送新鲜的前端技术文章javascript


clipboard.png

JavaScript 原语

JavaScript 创建在一系列基本单元之上。你应该对其中的一些已经很熟悉了,好比字符串和数字:css

var greet = "Hello";
var year = 89;

字符串和数字是该语言所谓“原语”的一部分。完整清单是:前端

  • String
  • Number
  • Boolean
  • Null
  • Undefined
  • Object
  • Symbol (ES6中添加,此处不予介绍)

布尔值用来表示多是真或假的值。 null 是故意不去赋值,它一般被分配给一个变量,用于表示绑定完毕,稍后将填充有意义的内容。java

var maybe = null;

而后才是 undefined,这意味着变量仍然没有被附加上:python

var name;
console.log(name)
undefined

null 和 undefined 看起来很是类似,但它们是两个大相径庭的实体,不少开发人员仍然不肯定应该使用哪一个git

若是要判断 JavaScript 实例的类型,能够用 typeof 运算符。让咱们用字符串尝试一下:程序员

typeof "alex"
> "string"

还有数字:github

typeof 9
> "number"

用于布尔值:面试

typeof false
> "boolean"

undefined:编程

typeof undefined
> "undefined"

还有 null:

typeof null
> "object"

结果使人惊讶! null 看起来像一个对象,但实际上它是 JavaScript 中的一个历史性错误,自语言诞生就躺在那里了。 因为这些问题,JavaScript 一直声名狼借。但这仅仅是个开始。

陌生的事情

在 JavaScript 中,在两种类型之间进行转换时有一些奇怪的规则。让我给你一些背景信息。先用 Python 举一个例子。 在 Python 中执行如下指令:

'hello' + 89

会给你一个明确的错误:

TypeError: can only concatenate str (**not** "int") to str

而在 JavaScript 中,只有天空才是你的极限:

'hello' + 89

事实上给出:

"hello89"

若是咱们尝试向字符串添加数组,看起来会更加奇怪:

'hello' + []

将会获得

1. 'hello'

还有

1. 'hello' + [89]

会给你一个惊喜:

1. "hello89"

看起来这种转换背后存在某种逻辑。它甚至适用于存在更多元素的 array :

1. 'hello' + [89, 150.156, 'mike']

获得:

1. "hello89,150.156,mike"

这两行 JavaScript 足以让 Java 程序员逃离。可是这种行为在 JavaScript 中 100% 是又意义的。所以这种隐式转换,也称为强制类型转换是很是值得探索的。

当一个数字变成一个字符串

一些编程语言有一个叫作类型转换的概念,这意味着:若是我想把一个数字或实例转换为另外一种类型,那么我必须使显式转换。它也适用于 JavaScript。请看如下示例:

var greet = "Hello";
var year = 89;

若是我想明确的进行转换,能够在代码中代表意图:

var greet = "Hello";
var year = 89;

var yearString = year.toString()

要么这样作:

var greet = "Hello";
var year = 89;

var yearString = String(year)

而后我能够链接两个变量:

greet + yearString;

可是在 JavaScript 中有一种被称为隐式转换的微妙机制,由 JavaScript 引擎提供。该语言不会阻止咱们对数字和字符串进行加法操做:

'hello' + 89

会获得:

"hello89"

可是这种转换背后的逻辑是什么?你可能会惊讶地发现 JavaScript 中的加法运算符 + 会自动将两个操做数中的任何一个都转换为字符串,若是其中至少有一个是字符串的话

你会发现更使人惊讶的是,这条规则在ECMAScript规范中一脉相承。 第11.6.1节 定义了加法运算符的行为,我在这里为你作了总结:

若是 x 是 String 或 y 是String,则返回 ToString(x),而后返回ToString(y)

这个花招只适用于数字吗?并非。 数组和对象也会受到相同的转换

'hello' + [89, 150.156, 'mike']

会获得:

"hello89,150.156,mike"

那么下面的代码会获得怎样的结果:

'hello' + { name: "Jacopo" }

要找到答案,你能够经过将对象转换为字符串来进行快速测试:

String({ name: "Jacopo" })

将会获得:

"[object Object]"

因此我有一种感受:

1. 'hello' + { name: "Jacopo" }

会获得:

1. "hello[object Object]"

打住!这又是什么?

JavaScript 中 [object Object] 的含义是什么?

“[object Object]” 是最多见的 JavaScript “怪癖”之一。

几乎每一个 JavaScript 实例都有一个名为 toString() 的方法,有些方法是由 Object.prototype.toString 提供的。
某些类型(如数组)实现了 toString() 的自定义版本,以便在调用方法时将值转换为字符串。例如 Array.prototype.toString 会覆盖 Object.toString()(也称为 method shadowing)。

可是当你在普通的 JavaScript 对象上调用 toString() 时,引擎会给出“[object Object]”,由于 Object.toString()默认行为是由实体类型(在这种状况下为Object)返回字符串 object

如今让咱们把注意力集中在 JavaScript 比较运算符上,它们与算术运算符同样奇怪。

等于仍是不等于?

JavaScript 中有两个主要的比较运算符。

第一个咱们称之为“弱比较”。这是抽象比较运算符(双等号):==

另外一个是“强比较”,能够经过三等号进行识别:=== 也称为严格比较运算符。它们二者的行为方式彻底不一样。

来看一些例子。首先,若是咱们将两个字符串与两个运算符进行比较,咱们获得相同的结果

"hello" == "hello"
> true

"hello" === "hello"
> true

看上去一切都还好。

如今尝试比较两种不一样的类型,数字和字符串。首先是“强比较”:

1. "1" === 1
2. false

这说得通!字符串“1”与数字1是不一样的。可是“弱比较”会发生什么?

1. "1" == 1
2. true

竟然是true!它没有任何意义,除非这种行为与咱们以前看到的隐式转换有关。

若是适用相同的规则怎么办?没错! ECMAScript spec 再次罢工。结果抽象比较运算符在比较它们以前在类型之间进行自动转换。这是规范的摘要:

比较 x == y 执行以下:

若是 x 是 String 且 y 是Number,则返回比较结果 ToNumber(x)== y

规范说:若是第一个操做数是一个字符串,第二个操做数是一个数字,那么将第一个操做数转换为数字。有趣。

JavaScript 规范充满了这个疯狂的规则,我强烈鼓励你们对它深刻挖掘。

在此期间除非你有充分的理由不然在 JavaScript 代码中避免使用抽象比较运算符。你之后会感谢本身的。

那么“强势比较”怎么样?规范中的说 严格相等比较在把值与三等 === 进行比较以前没有进行自动转换。在代码中使用严格相等比较能够避免愚蠢的 bug。

总结

JavaScript 中有七个构建块,即 StringNumberBooleanNullUndefinedObjectSymbol。这些类型被称为基元

JavaScript 开发人员可使用算术和比较运算符来操做这些类型。可是咱们要特别注意加法运算符 +抽象比较运算符 ==,它本质上倾向于在类型之间进行转换。

JavaScript 中的隐式转换称为强制类型转换,并在 ECMAScript 规范中定义。不管何时你的代码都要使用严格的比较运算符 === 而不是 ==

做为最佳实践,当你打算在两种类型之间进行转换时,请务必明确操做。JavaScript 有一堆内置对象,它们反映了原始类型:StringNumberBoolean。这些内置类型可用于在不一样类型之间进行显式转换。


本文首发微信公众号:前端先锋

欢迎扫描二维码关注公众号,天天都给你推送新鲜的前端技术文章

欢迎扫描二维码关注公众号,天天都给你推送新鲜的前端技术文章


欢迎继续阅读本专栏其它高赞文章:

相关文章
相关标签/搜索