详解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实现带关闭按钮的网页漂浮广告代码
Jan 12 Javascript
JS+CSS模拟可以无刷新显示内容的留言板实例
Mar 03 Javascript
BootStrap中的table实现数据填充与分页应用小结
May 26 Javascript
解析JavaScript中的字符串类型与字符编码支持
Jun 24 Javascript
React 子组件向父组件传值的方法
Jul 24 Javascript
Bootstrap4如何定制自己的颜色和风格
Feb 26 Javascript
JavaScript 下载svg图片为png格式
Jun 21 Javascript
全面解析vue router 基本使用(动态路由,嵌套路由)
Sep 02 Javascript
jQuery表单选择器用法详解
Aug 22 jQuery
vue实现吸顶、锚点和滚动高亮按钮效果
Oct 21 Javascript
如何利用javascript接收json信息并进行处理
Aug 06 Javascript
vue 递归组件的简单使用示例
Jan 14 Vue.js
一个小时快速搭建微信小程序的方法步骤
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获取金书网的书名的实现代码
2010/06/11 PHP
php中DOMElement操作xml文档实例演示
2013/03/26 PHP
Laravel 5 学习笔记
2015/03/06 PHP
php支持中文字符串分割的函数
2015/05/28 PHP
Yii 2.0实现联表查询加搜索分页的方法示例
2017/08/02 PHP
thinkPHP利用ajax异步上传图片并显示、删除的示例
2018/09/26 PHP
laravel框架的安装与路由实例分析
2019/10/11 PHP
javascript offsetX与layerX区别
2010/03/12 Javascript
IE6下js通过css隐藏select的一个bug
2010/08/16 Javascript
JS 跳转页面延迟2种方法
2013/03/29 Javascript
node.js中的buffer.write方法使用说明
2014/12/10 Javascript
JavaScript列表框listbox全选和反选的实现方法
2015/03/18 Javascript
js中this用法实例详解
2015/05/05 Javascript
jquery使整个div区域可以点击的方法
2015/06/24 Javascript
Js查找字符串中出现次数最多的字符及个数实例解析
2016/09/05 Javascript
Vue.js组件tabs实现选项卡切换效果
2016/12/01 Javascript
Javascript防止图片拉伸的自适应处理方法
2017/12/26 Javascript
JavaScript事件发布/订阅模式原理与用法分析
2018/08/21 Javascript
websocket4.0+typescript 实现热更新的方法
2019/08/14 Javascript
node.js中 redis 的安装和基本操作示例
2020/02/10 Javascript
javascript设计模式 ? 抽象工厂模式原理与应用实例分析
2020/04/09 Javascript
JS如何实现封装列表右滑动删除收藏按钮
2020/07/23 Javascript
CentOS6.5设置Django开发环境
2016/10/13 Python
总结python实现父类调用两种方法的不同
2017/01/15 Python
Python实现读取邮箱中的邮件功能示例【含文本及附件】
2017/08/05 Python
解决Keras使用GPU资源耗尽的问题
2020/06/22 Python
python中如何写类
2020/06/29 Python
使用jupyter notebook运行python和R的步骤
2020/08/13 Python
Python正则re模块使用步骤及原理解析
2020/08/18 Python
Python存储读取HDF5文件代码解析
2020/11/25 Python
css3制作动态进度条以及附加jQuery百分比数字显示
2012/12/13 HTML / CSS
TripAdvisor斯洛伐克:阅读评论、比较价格和酒店预订
2018/04/25 全球购物
优质的学校老师推荐信
2013/10/28 职场文书
四风问题对照检查材料
2014/09/22 职场文书
保护校园环境倡议书
2015/04/28 职场文书
详解MySQL数据库千万级数据查询和存储
2021/05/18 MySQL