JavaScript 在 运算 或 比较 之前, 会自动进行隐式类型转换. 下面我们来仔细讲一讲 + - * / == 运算符经历了哪些过程.

类型转换

ECMAScript 运行时系统会在需要时从事自动类型转换。为了阐明某些结构的语义,定义一集转换运算符是很有用的。这些运算符不是语言的一部分;在这里定义它们是为了协助语言语义的规范。

  • ToPrimitive
  • ToNumber
  • ToString
  • ToBoolean
  • ToInteger
  • ToInt32:(32 位有符号整数)
  • ToUint32:(32 位无符号整数)
  • ToUint16:(16 位无符号整数)
  • ToObject

下面详细讲讲前三种

ToPrimitive

转为原始类型.

ToPrimitive(input, PreferredType)
输入类型 结果
Undefined 结果等于输入的参数(不转换)。
Null 结果等于输入的参数(不转换)。
Boolean 结果等于输入的参数(不转换)。
Number 结果等于输入的参数(不转换)。
String 结果等于输入的参数(不转换)。
Object 返回该对象的默认值。
对象的默认值由把 PreferredType 传入作为hint参数调用对象的内部方法[[DefaultValue]]得到

对象内部方法 [[DefaultValue]] (hint)

当用 String hint 调用 O 的 [[DefaultValue]] 内部方法,采用以下步骤:

  1. str = O.toString();
  2. 如果str为原始值,返回str;
  3. val = O.valueOf();
  4. 如果val为原始值,返回val;
  5. 抛出一个 TypeError 异常。

当用 Number hint 调用 O 的 [[DefaultValue]] 内部方法,采用以下步骤:

  1. val = O.valueOf();
  2. 如果val为原始值,返回val;
  3. str = O.toString();
  4. 如果str为原始值,返回str;
  5. 抛出一个 TypeError 异常。

当不用 hint 调用 O 的 [[DefaultValue]] 内部方法时, 如果 O 为Date, 则hint=String, 除此之外, hit=Number。

例子:

ToPrimitive({})
解析:
数据类型为 Object, 调用[[DefaultValue]]
没有用 hint 调用, 则 hint 为 Number
val = O.valueOf();
val 是 {}, 不是原始值
str = O.toString();
str 是 '[object Object]', 是原始值, 返回'[object Object]'
结果: '[object Object]'

ToNumber

转为数字类型.(是 Number(value) 的实现)

Input Type Result
Undefined NaN
Null +0
Boolean true: 1, false: +0
Number 结果等于输入的参数(不转换)。
String 将字符串转换为数字。
Object Apply the following steps:
1. Call ToPrimitive(input argument, hint Number).
2. Call ToNumber(Result(1)).
3. Return Result(2).

ToString

转为字符串类型.(是 String(value) 的实现)

输入类型 结果
Undefined "undefined"
Null "null"
Boolean 如果参数是 true,那么结果为 "true"。
如果参数是 false,那么结果为 "false"。
Number 将数字转换为字符串。
String 结果等于输入的参数(不转换)。
Object Apply the following steps:
1. Call ToPrimitive(input argument, hint String).
2. Call ToString(Result(1)).
3. Return Result(2).

例子:

var obj = {
valueOf: function () {
return 1;
},
toString: function () {
return 2;
}
} Number(obj)
解析:
obj 类型 Object, 调用 ToPrimitive(obj, Number)
用 Number hint 调用 obj 的 [[DefaultValue]] 内部方法
调用 obj 的 valueOf 方法, 结果为 1
返回 ToNumber(1)
结果: 1 String(obj)
解析:
obj 类型 Object, 调用 ToPrimitive(obj, String)
用 String hint 调用 obj 的 [[DefaultValue]] 内部方法
调用 obj 的 toString 方法, 结果为 2
返回 ToString(2)
结果: '2'

类型转换的实际运用

加号运算符:+

lval + rval 运算流程如下:

  1. 令 lprim 为 ToPrimitive(lval).
  2. 令 rprim 为 ToPrimitive(rval).
  3. 如果 Type(lprim) 为 String 或者 Type(rprim) 为 String,则: 返回由 ToString(lprim) 和 ToString(rprim) 连接而成的字符串.
  4. 返回将加法运算作用于 ToNumber(lprim) 和 ToNumber(rprim) 的结果.

例子:

([] + {})
解析:
1. lprim = ToPrimitive([]); // ''
2. rprim = ToPrimitive({}); // '[object Object]'
3. lprim 和 rprim 都为字符串, 返回 ToString('') + ToString('[object Object]') // '[object Object]'
结果: '[object Object]' (undefined + {})
解析:
1. lprim = ToPrimitive([]); // undefined;
2. rprim = ToPrimitive({}); // '[object Object]';
3. Type(rprim) 为 String, 返回 ToString(undefined) + ToString('[object Object]') // 'undefined[object Object]'
结果: 'undefined[object Object]' (undefined + 1)
解析:
1. lprim = ToPrimitive([]); // undefined;
2. rprim = ToPrimitive(1); // 1;
3. Type(lprim) Type(rprim) 都不是 String;
4. 返回 ToNumber(undefined) + ToNumber(1) // NaN
结果: NaN

其他运算符:- * /

lval 和 rval 的 - * / 运算符流程如下:

  1. 令 lnum 为 ToNumber(lval).
  2. 令 rnum 为 ToNumber(rval).
  3. 返回 ToNumber(lprim) 和 ToNumber(rprim) 运算的结果.

非严格相等:==

被比较值 B
Undefined Null Number String Boolean Object
被比较值 A Undefined true true false false false IsFalsy(B)
Null true true false false false IsFalsy(B)
Number false false A === B A === ToNumber(B) A=== ToNumber(B) A== ToPrimitive(B)
String false false ToNumber(A) === B A === B ToNumber(A) === ToNumber(B) ToPrimitive(B) == A
Boolean false false ToNumber(A) === B ToNumber(A) === ToNumber(B) A === B ToNumber(A) == ToPrimitive(B)
Object false false ToPrimitive(A) == B ToPrimitive(A) == B ToPrimitive(A) == ToNumber(B)

A === B

例子:

[] == {}
-> this == this
-> false [] == 0
-> ToPrimitive([]) == 0
-> '' == 0
-> ToNumber('') == 0
-> 0 == 0
-> true [0] == 0
-> ToPrimitive([0]) == 0
-> '0' == 0
-> ToNumber('0') == 0
-> 0 == 0
-> true [11] == 11
-> true ['0'] == false
-> ToPrimitive(['0']) == ToNumber(false)
-> '0' == 0
-> 0 == 0
-> true ({} == '[object Object]')
-> ToPrimitive({}) == '[object Object]'
-> '[object Object]' == '[object Object]'
-> true

 

参考

JavaScript隐式类型转换(详解 +,-,*,/,==)的更多相关文章

  1. javascript隐式转换详解

    Javascript是web前端开发的必学技术,今天和大家分享的就是javascript的基础知识隐式转换,希望可以帮助大家更好的学习. 转换成布尔类型假 undefined->falSe nu ...

  2. Scala进阶之路-Scala高级语法之隐式(implicit)详解

    Scala进阶之路-Scala高级语法之隐式(implicit)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 我们调用别人的框架,发现少了一些方法,需要添加,但是让别人为你一 ...

  3. JavaScript 隐式类型转换

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

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

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

  5. 四种JavaScript隐式类型转换的总结

    一般存在四种情况,JavaScript会对变量的数据类型进行转换. 目录 * if中的条件会被自动转为Boolean类型 * 会被转为false的数据 * 会被转为true的数据 * 参与+运算都会被 ...

  6. 对存在JavaScript隐式类型转换的四种情况的总结

    一般存在四种情况,JavaScript会对变量的数据类型进行转换. 目录 * if中的条件会被自动转为Boolean类型 * 会被转为false的数据 * 会被转为true的数据 * 参与+运算都会被 ...

  7. JavaScript 隐式类型转换之:加号+

    加号+,有些情况下,它是算术加号,有些情况下,是字符串连接符号 如果字符串和数字相加,JavaScript会自动把数字转换成字符,不管数字在前还是字符串在前 "2" + 3; // ...

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

    原文:JavaScript quirk 1: implicit conversion of values 译文:「译」JavaScript 的怪癖 1:隐式类型转换 译者:justjavac 零:提要 ...

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

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

随机推荐

  1. 吴裕雄--天生自然 R语言开发学习:高级编程

    运行的条件是一元逻辑向量(TRUE或FALSE)并且不能有缺失(NA).else部分是可选的.如果 仅有一个语句,花括号也是可以省略的. 下面的代码片段是一个例子: plot(x, y) } else ...

  2. centos7系统盘变为只读文件的修复

    一台物理机的系统盘在磁盘空间有剩余的情况下变为只读了,咨询后发现前几日修改过系统,然后就不可写了,重启也不行.见下图 解决:参考链接https://bbs.51cto.com/thread-92640 ...

  3. Spring中的事件处理

    文章目录 Spring中的事件处理 Spring 的核心是 ApplicationContext,它负责管理 beans 的完整生命周期.当加载 beans 时,ApplicationContext ...

  4. 从wordpress换hexo博客后

    之前用wordpress做blog, 为什么换为hexo呢? 第一 ​ wordpress的文章都保存在服务器的数据库, 维护不是很直观. ​ 而hexo是自己编写markdown文章,本地一份,而b ...

  5. Spring源码分析-BeanFactoryPostProcessors 应用之 PropertyPlaceholderConfigurer

    BeanFactoryPostProcessors 介绍 BeanFactoryPostProcessors完整定义: /** * Allows for custom modification of ...

  6. java反序列化-ysoserial-调试分析总结篇(3)

    前言: 这篇文章主要分析commoncollections3,这条利用链如yso描述,这个与cc1类似,只是反射调用方法是用的不是invokeTransformer而用的是InstantiateTra ...

  7. H5页面通用头部设置

    见到很多人写H5页面都不设置头部,不忍直视,于是整理一篇文章,不定期更新,为了让自己显得专业一点,也为了方便自己复制粘贴 一般来说必须设置项 <!-- 页面编码 --> <meta ...

  8. 前端每日实战:7# 视频演示如何用纯 CSS 创作一个 3D 文字跑马灯特效

    效果预览 按下右侧的"点击预览"按钮在当前页面预览,点击链接全屏预览. https://codepen.io/zhang-ou/pen/GdrrZq 可交互视频教程 此视频是可以交 ...

  9. python从一个目录中复制全部文件图片至另一个目录中,及删除指定目录中的图片

    import shutil import os #目录自己改一下即可,复制 path = "./static/imgs/" new_path = "./static/up ...

  10. 斐讯k2

    降级方法 https://jingyan.baidu.com/article/ab69b27080990d2ca7189f0b.html 刷第三方固件方法 https://blog.csdn.net/ ...