前言

最近和大创扯淡时说到了[] == false,从结果上来看我俩都答错了,从气势上来说我俩的歪理都能出书了(恩,程序猿的骄傲),但是这其实背后隐藏了一潭很深的水,对,很深。。。

隐式类型转换

JS的数据类型

首先,回想一下JS的类型都有什么。

原始值(primitives): undefined, null, booleans, numbers,strings, symbol(es6)

对象值(objects): Object

ok, 这就是全部了,我们接下来看看到底发生了什么导致隐式转换如此不可捉摸。

ToPrimitive

在发生转换的时候,js其实都是会将操作对象转化为原始的对象,这也是最为诟病的地方,因为js很难直接抛出错误,她会用一套自己的方法去理解我们的错误,并做相应的调整,哪怕这些错误我们是无意识的。所以我们要知道她的转换方式,才能做到知己知彼,对代码的控制更为精准。

签名:ToPrimitive(input, PreferredType?) //PreferredType: Number 或者 String

流程如下:

  1. input为原始值,直接返回;
  2. 不是原始值,调用该对象的valueOf()方法,如果结果是原始值,返回原始值;
  3. 调用valueOf()不是原始值,调用此对象的toString()方法,如果结果为原始值,返回原始值;
  4. 如果返回的不是原始值,抛出异常TypeError。

其中PreferredType控制线调取valueOf()还是toString()。

ps: Date类型按照String去调用。

ok,通过这个隐式装箱,我们得到了操作数的原始值。接下来,我们根据不同情况,看看发生了什么呢~

数学运算

想必大家用过以下做法去完成类型转换吧

var str = '1';
var num = str - 0; var num = 2;
var str = num + '';

这种类似的数学运算会做类型转换,*/-操作符都是数字运算专用的。当这些运算符与字符串一起使用时,会强制转换字符串为数字类型的值。但是‘+’尤为致命,为啥捏?

当'+'作为双目运算符时,如a+b。

它的运行如下:

  1. 计算两个操作数的原始值: prima = ToPrimitive(a), prima = ToPrimitive(b);
  2. 如果原始值有String,全部转换为String,返回String相加后的结果;
  3. 如果原始值没有String,全部转换为Number, 返回Number相加后的结果;

当'+'作为单目运算符时, 例如 +a.

流程是这样的:

  1. 将a转换为Number,Number(a);

举个栗子:

[] + []

1. 转换为原始类型 toPrimitive([]);

[].valueOf();//[],不是原始类型

[].toString();//"",真是令人发指的转换

2. 都为string,所以返回字符串想家的结果

return "" + "";

{} + [] 与 [] + {}

{} + []
1. 在浏览器中,JS引擎认为第一个{}为空代码块,所以 这里的 '+'是单目运算符(node中认为是对象,解析为"[object Object]") ToPrimitive([]); //"" 2. Number("");// [] + {}
1. ToPrimitive([]); //""
ToPrimitive({}); //"[object Object]" 2. 都为string
return "" + "[object Object]";//"[object Object]"

PS: [].valueOf 为[], 但在ES6中JS会优先调用[Symbol ToPrimitive]来转换为原始类型。

比较运算

首先,比较运算分为2种, 一种为严格比较(===),只有类型相等,值也一致时才会为true,否则为false, 另一种为抽象相等也叫宽松相等(==),先将运算数转化为相同类型,再做比较,具体过程见 Abstract Equality Comparison Algorithm

这个算法大致说了这么几个情况,x == y

  • xy都为Null或undefined,return true;
  • x或y为NaN, return false;
  • 如果x和y为String,Number,Boolean并且类型不一致,都转为Number再进行比较
  • 如果存在Object,转换为原始值,比较

回到这篇文章的导火索,[] == false

1.存在object, 转化为原始值
ToPrimitive([]); // '' 2.一个string, 另外为boolean,都转为number
Number('');//
Number(false);// 3.return 0 == 0;/true

备注

ToPrimitive

 value toNumber  toString  toBoolean 
 NaN  NaN  "NaN"  false
 Infinity  Infinity  "Infinity"  true
 []  0  '""  true
 [1]  1  "1"  true
null 0 "null" false
undefined NaN "undefined" false
{} NaN "[object Object]" true
function() NaN "function" true

ToNumber

ToString

2017/12/05

winking说了一个简便的方法去理解[] toPrimitive = ‘’ , 想成join()就好了 (*^▽^*)

JS的隐式转换 从 [] ==false 说起的更多相关文章

  1. js数据类型隐式转换问题

    js数据类型隐式转换 ![] == false //true 空数组和基本类型转换,会先[].toString() 再继续比较 ![] == [] //true ![] //false [] == [ ...

  2. js 的隐式转换与显式转换

    隐式转换   1.undefined与null相等,但不恒等(===) 2.一个是number一个是string时,会尝试将string转换为number 3.隐式转换将boolean转换为numbe ...

  3. JS的类型转换,强制转换和隐式转换

    JS的类型转换 1.强制转换 通过String(),Number(),Boolean()函数强制转换 var str=123; var str1='123'; console.log(typeof s ...

  4. js学习日记-隐式转换相关的坑及知识

    隐式转换比较是js中绕不过去的坎,就算有几年经验的工程师也很有可能对这块知识不够熟悉.就算你知道使用===比较从而避免踩坑,但是团队其它成员不一定知道有这样或那样的坑,有后端语言经验的人常常会形成一个 ...

  5. js中的一些隐式转换和总结

    js中的不同的数据类型之间的比较转换规则如下: 1. 对象和布尔值比较 对象和布尔值进行比较时,对象先转换为字符串,然后再转换为数字,布尔值直接转换为数字 [] == true; //false [] ...

  6. Js 中那些 隐式转换

    曾经看到过这样一个代码:  (!(~+[])+{})[--[~+""][+[]]*[~+[]]+~~!+[]]+({}+[])[[~!+[]*~+[]]] = sb , 你敢相信, ...

  7. js中的数据类型隐式转换的三种情况

    js的数据类型隐式转换主要分为三种情况: 1. 转换为boolean类型 2. 转换为number类型 3. 转换为string类型 转换为boolean类型 数据在 逻辑判断 和 逻辑运算 之中会隐 ...

  8. ECMAScript1.1 js书写位置 | 声明变量 | 基本数据类型 | 数据类型转换 | 操作符 | 布尔类型的隐式转换

    js书写位置 由于在写css样式时使用的时双引号,所以我们在写js代码时建议使用单引号(‘’)! 行内式 <input type="button" value="点 ...

  9. js隐式转换

    JavaScript的数据类型分为六种,分别为null,undefined,boolean,string,number,object.object是引用类型,其它的五种是基本类型或者是原始类型.我们可 ...

随机推荐

  1. 负载均衡集群企业级应用实战—LVS

    一.负载均衡集群介绍 1.集群 ① 集群(cluster)技术是一种较新的技术,通过集群技术,可以在付出较低成本的情况下获得在性能.可靠性.灵活性方面的相对较高的收益,其任务调度则是集群系统中的核心技 ...

  2. C++获取本机IP等信息

    运行环境:VS2008,win7,代码来源于MSDN,相关函数可以查看MSDN中的函数定义.. 代码如下: #include <winsock2.h> #include <ws2tc ...

  3. spring框架应用系列三:切面编程(带参数)

    本文系作者原创,转载请注明出处:http://www.cnblogs.com/further-further-further/p/7786715.html 解决问题 1.分离业务监控与业务处理.简单点 ...

  4. D3.js从入门到“放弃”指南

    前言 近期略有点诸事不顺,趁略有闲余之时,玩起D3.js.之前实际项目中主要是用各种chart如hightchart.echarts等,这些图形库玩起来貌都是完美的,一切皆可配置,但几年前接触了D3之 ...

  5. File API简介

    File API让我们可以创建文件,存储在本地文件系统的一个安全沙箱里,亦可以从其他来源读取文件,并对其进行操作   Web应用通过requestFileSystem方法来访问本地文件系统,该方法是全 ...

  6. arguments对象

    改变函数arguments也会改变对应的参数,arguments会自动映射到对应的参数上 但是改变参数并不会同步改变arguments 它们并不公用内存 在strict模式,不能对arguments付 ...

  7. python 3---if判断成绩练习

    需求根据用户输入的成绩分档,要求如下: 1. 如果成绩大于60分,输出"及格"2. 如果成绩大于70分,输出"良"3. 如果成绩大于80分,输出"好& ...

  8. 如何优雅的设计 React 组件

    作者:晓冬 本文原创,转载请注明作者及出处 如今的 Web 前端已被 React.Vue 和 Angular 三分天下,一统江山十几年的 jQuery 显然已经很难满足现在的开发模式.那么,为什么大家 ...

  9. OpenCV二维Mat数组(二级指针)在CUDA中的使用

    CUDA用于并行计算非常方便,但是GPU与CPU之间的交互,比如传递参数等相对麻烦一些.在写CUDA核函数的时候形参往往会有很多个,动辄达到10-20个,如果能够在CPU中提前把数据组织好,比如使用二 ...

  10. Windows常用shell命令大全

    Windows常用shell命令大全 基于鼠标操作的后果就是OS界面外观发生改变, 就得多花学习成本.更主要的是基于界面引导Path与命令行直达速度是难以比拟的.另外Geek很大一部分是键盘控,而非鼠 ...