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. Ionic3学习笔记(十六)上传头像至图床

    本文为原创文章,转载请标明出处 个人做的开源 Demo 登录注册模块采用的是 Wilddog 野狗通讯云的身份认证服务,不得不说各方面和 Google 收购的 Firebase 很像,十分简单易用.其 ...

  2. 吴裕雄--天生自然 R语言开发学习:使用ggplot2进行高级绘图(续二)

    #----------------------------------------------------------# # R in Action (2nd ed): Chapter 19 # # ...

  3. 亚马逊Prime会员的杀价,能说明会员+会越来越便宜吗?

    前段时间,京东又坑了!京东调整了物流方案--从原来的购物不满49元只需6元运费,调整到购物不满46元运费15元,运费猛涨了9元!原本京东PLUS会员每月有5张免运费券,但在运费涨价后运费券限制在6元, ...

  4. Python不使用元类创建缓存实例

    问题 当创建类实例时我们想返回一个缓存引用,让其指向上一个用同样参数(如果有的话)创建出来的类实例. 这个问题常常出现在当我们想确保针对一组输入参数只会有一个类实例存在时. 解决方法: 使用一个与类本 ...

  5. 将java project打包成jar包,web project 打包成war包的几种演示

    将java项目打包成jar 第一种:MyEclipse将java项目打包成jar. 1,右击项目,选择export . 2,点击Java,选择JAR file . 3,在JAR file文本中浏览打包 ...

  6. const define static extern

    const const意味着"只读",欲阻止一个变量被改变,可以使用const关键字 const仅仅用来修饰右边的变量(基本数据变量p,指针变量*p) define #define ...

  7. ansible使用指北(二)

    前言在上一篇文章里我们了解了ansible的常用模块,今天我们来了解下ansible-playbook,ansbile-playbook是一系统ansible命令的集合,其利用yaml 语言编写,an ...

  8. 百度地图API:使用百度定位

    准备工作: 1.申请百度地图API 2.下载百度地图的SDK 3.将SDK包中的BaiduLBS_Android.jar文件放到,项目里的app/libs里面 4.在src/main目录下创建一个名为 ...

  9. docker学习读书笔记-一期-整理

    0.Docker - 第零章:前言 1.Docker - 第一章:Docker简介 2.Docker - 第二章:第一个Docker应用 3.Docker - 第三章:Docker常用命令 4.Doc ...

  10. 记录一下自己写PHP程序时走过的一些坑

    写在前面: 喔噢,转眼间发现自己正式开发程序(PHP)已经有快有1个月了,一路上走了许多的坑,有时遇到坑的时候真想放弃,但是还是坚持下来了!所以写了这篇文章来帮助那些刚刚接触PHP的小白们.[: )] ...