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. gin源码剖析

    介绍 Gin 是一个 Golang 写的 web 框架,具有高性能的优点,基于 httprouter,它提供了类似martini但更好性能(路由性能约快40倍)的API服务.官方地址:https:// ...

  2. <JZOJ5913>林下风气

    快乐dp 反正考场写挂 #include<cstdio> #include<cstring> #include<cctype> #include<iostre ...

  3. OS Summary 1

    内容概述 什么是操作系统 操作系统的演变 操作系统结果的分类 什么是操作系统 操作系统可以是: 一个控制程序 一个资源管理器 一套标准库 操作系统通常有内核.命令行和 GUI 组成.我们研究的主要是内 ...

  4. js 中 == 和 === 的区别

    js中的 ==和===的区别 简单理解 js 是弱类型的语言,其中 == 可以理解为 是值是否相等,而===不仅比较值是否相等,还比较类型是否相等. 简单案例: var str = "1&q ...

  5. python标准库-array 模块

    原文地址:http://www.bugingcode.com/blog/python_module_array.html array 模块是python中实现的一种高效的数组存储类型.它和list相似 ...

  6. 吴裕雄--天生自然KITTEN编程:一箭穿心

  7. Selenium&Pytesseract模拟登录+验证码识别

    验证码是爬虫需要解决的问题,因为很多网站的数据是需要登录成功后才可以获取的. 验证码识别,即图片识别,很多人都有误区,觉得这是爬虫方面的知识,其实是不对的. 验证码识别涉及到的知识:人工智能,模式识别 ...

  8. –IDEA+Maven+JavaWeb+tomcat项目搭建(图文并茂,详细)

    一.创建Maven项目 1:如果刚打开IDEA,显示的是这个页面,我们直接单击 Create New Project(创建项目) 或者 File-> New-> Project 2:选中左 ...

  9. array, matrix, list and dataframe

    总结一下"入门3R"(Reading, 'Riting, 'Rrithmetic)中的读和写,不同的数据结构下的读写还是有点区别的. vector 命名 12 month.days ...

  10. c#百度IP定位API使用方法

    c#百度IP定位API使用方法 1.先建立一个收集信息的实体类 IPModel.cs: using System; using System.Collections.Generic; using Sy ...