详解JavaScript中的强制类型转换


Posted in Javascript onApril 15, 2019

avaScript 原语

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

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

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

  1. String
  2. Number
  3. Boolean
  4. Null
  5. Undefined
  6. Object
  7. Symbol (ES6中添加,此处不予介绍)

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

var maybe = null;

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

var name;
console.log(name)
undefined

null 和 undefined 看起来非常相似,但它们是两个截然不同的实体,很多开发人员仍然不确定应该使用哪个。

如果要判断 JavaScript 实例的类型,可以用 typeof 运算符。让我们用字符串尝试一下:

typeof "alex"
> "string"

还有数字:

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' + []

将会得到

 'hello'

 还有

'hello' + [89]

 会给你一个惊喜:

 "hello89"

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

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

得到:

"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]"

 所以我有一种感觉:

'hello' + { name: "Jacopo" }

会得到:

"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
false

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

"1" == 1
 true

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

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

比较 x == y 执行如下:
如果 x 是 String 且 y 是Number,则返回比较结果 ToNumber(x)== y
规范说:如果第一个操作数是一个字符串,第二个操作数是一个数字,那么将第一个操作数转换为数字。有趣。

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

在此期间除非你有充分的理由否则在 JavaScript 代码中避免使用抽象比较运算符。你以后会感谢自己的。

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

总结

JavaScript 中有七个构建块,即 String,Number,Boolean,Null,Undefined,Object 和 Symbol。这些类型被称为基元。

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

以上所述是小编给大家介绍的JavaScript中的强制类型转换详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
Javascript Jquery 遍历Json的实现代码
Mar 31 Javascript
jQuery使用empty()方法删除元素及其所有子元素的方法
Mar 26 Javascript
18个非常棒的jQuery代码片段
Nov 02 Javascript
jQuery-1.9.1源码分析系列(十)事件系统之事件包装
Nov 20 Javascript
jquery.validate提示错误信息位置方法
Jan 22 Javascript
JavaScript函数表达式详解及实例
May 05 Javascript
VUE2.0+Element-UI+Echarts封装的组件实例
Mar 02 Javascript
对angular4子路由&辅助路由详解
Oct 09 Javascript
js获取 gif 的帧数的代码实例
Sep 10 Javascript
layer ui插件显示tips时,修改字体颜色的实现方法
Sep 11 Javascript
angula中使用iframe点击后不执行变更检测的问题
May 10 Javascript
利用JavaScript写一个简单计算器
Nov 27 Javascript
一个小时快速搭建微信小程序的方法步骤
Apr 15 #Javascript
详解从0开始搭建微信小程序(前后端)的全过程
Apr 15 #Javascript
ES6知识点整理之模块化的应用详解
Apr 15 #Javascript
详解如何运行vue项目
Apr 15 #Javascript
vue单页面在微信下只能分享落地页的解决方案
Apr 15 #Javascript
vue--vuex详解
Apr 15 #Javascript
详解如何模拟实现node中的Events模块(通俗易懂版)
Apr 15 #Javascript
You might like
php base64 编码与解码实例代码
2017/03/21 PHP
php删除一个路径下的所有文件夹和文件的方法
2018/02/07 PHP
在TP5数据库中四个字段实现无限分类的示例
2019/10/18 PHP
javascript 语法基础 想学习js的朋友可以看看
2009/12/16 Javascript
js/jquery获取文本框输入焦点的方法
2014/03/04 Javascript
js如何判断用户是在PC端和还是移动端访问
2014/04/24 Javascript
JQuery控制图片由中心点逐渐放大效果
2016/06/26 Javascript
javascript工厂模式和构造函数模式创建对象方法解析
2016/12/30 Javascript
js轮播图透明度切换(带上下页和底部圆点切换)
2017/04/27 Javascript
Node.js+Express+MySql实现用户登录注册功能
2017/07/10 Javascript
python爬取安居客二手房网站数据(实例讲解)
2017/10/19 Javascript
JavaScript中变量、指针和引用功能与操作示例
2018/08/04 Javascript
ES10 特性的完整指南小结
2019/03/04 Javascript
中级前端工程师必须要掌握的27个JavaScript 技巧(干货总结)
2019/09/23 Javascript
vue仿ios列表左划删除
2019/09/26 Javascript
JavaScript图像放大镜效果实现方法详解
2020/06/28 Javascript
python内存管理分析
2015/04/08 Python
浅析Python 3 字符串中的 STR 和 Bytes 有什么区别
2018/10/14 Python
Python语言检测模块langid和langdetect的使用实例
2019/02/19 Python
PyCharm中代码字体大小调整方法
2019/07/29 Python
解决Pycharm 导入其他文件夹源码的2种方法
2020/02/12 Python
Matplotlib自定义坐标轴刻度的实现示例
2020/06/18 Python
python中format函数如何使用
2020/06/22 Python
美国大型的健身社区和补充商店:Bodybuilding.com
2016/09/06 全球购物
Luxplus瑞典:香水和美容护理折扣
2018/01/28 全球购物
Hotter Shoes美国官网:英国最受欢迎的舒适鞋
2018/08/02 全球购物
The North Face意大利官网:服装、背包和鞋子
2020/06/17 全球购物
个人找工作的自我评价
2013/10/17 职场文书
《找不到快乐的波斯猫》教学反思
2014/02/24 职场文书
酒店七夕情人节活动策划方案
2014/08/24 职场文书
法人代表身份证明书及授权委托书
2014/09/16 职场文书
2014年财务工作总结范文
2014/11/11 职场文书
2015社区六五普法工作总结
2015/04/21 职场文书
2016元旦晚会主持词
2015/07/01 职场文书
初三毕业感言
2015/07/31 职场文书
如何利用Python实现一个论文降重工具
2021/07/09 Python