博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
你不知道的JavaScript中的数值转换
阅读量:6219 次
发布时间:2019-06-21

本文共 4068 字,大约阅读时间需要 13 分钟。

console.log(null == false);

开门见山,说出你的答案! 对,没错,答案是false! 让我们一探究竟吧!

规定

先来阅读以下两份规则:

严格相等 === :

全等操作符比较两个值是否相等,两个被比较的值在比较前都不进行隐式转换。如果两个被比较的值具有不同的类型,这两个值是不全等的。否则,如果两个被比较的值类型相同,值也相同,并且都不是 number 类型时,两个值全等。最后,如果两个值都是 number 类型,当两个都不是 NaN,并且数值相同,或是两个值分别为 +0 和 -0 时,两个值被认为是全等的。

var num = 0;var obj = new String("0");var str = "0";var b = false;console.log(num === num); // trueconsole.log(obj === obj); // trueconsole.log(str === str); // trueconsole.log(num === obj); // falseconsole.log(num === str); // falseconsole.log(obj === str); // falseconsole.log(null === undefined); // falseconsole.log(obj === null); // falseconsole.log(obj === undefined); // false复制代码

相等运算== :

The comparison x == y, where x and y are values, produces true or false.

  1. 如果x不是正常值(比如抛出一个错误),中断执行。
  2. 如果y不是正常值,中断执行。
  3. 如果Type(x)与Type(y)相同,执行严格相等运算x === y。
  4. 如果x是null,y是undefined,返回true。
  5. 如果x是undefined,y是null,返回true。
  6. 如果Type(x)是数值,Type(y)是字符串,返回x == ToNumber(y)的结果。
  7. 如果Type(x)是字符串,Type(y)是数值,返回ToNumber(x) == y的结果。
  8. 如果Type(x)是布尔值,返回ToNumber(x) == y的结果。
  9. 如果Type(y)是布尔值,返回x == ToNumber(y)的结果。
  10. 如果Type(x)是字符串或数值或Symbol值,Type(y)是对象,返回x == ToPrimitive(y)的结果。
  11. 如果Type(x)是对象,Type(y)是字符串或数值或Symbol值,返回ToPrimitive(x) == y的结果。
  12. return false。

那么我们提炼以下规则:

  1. 如果 x或者y不是正常值,中断执行。
  2. 如果 typeof x 和typeof y相同,执行x === y。
  3. 如果 x和y分别是null和undefined,返回true。
  4. 如果 x和y分别是数值和字符串类型,那么返回 x == Number(y) (y 为字符串)
  5. 如果 x和y其中一个为布尔类型,那么返回x == Number(y) (若 x 为布尔类型)
  6. 如果 x和y分别是(Symbol值 或 数值 或 字符串) 和 对象,返回x == ToPrimitive(y) (若 y 为对象)
  7. return false

1、将值转为原始值,ToPrimitive()。

2、将值转为数字,ToNumber()。

3、将值转为字符串,ToString()。

1.ToPrimitive()

js引擎内部的抽象操作ToPrimitive有着这样的签名: ToPrimitive(input, PreferredType?) input是要转换的值,PreferredType是可选参数,可以是Number或String类型。他只是一个转换标志,转化后的结果并不一定是这个参数所值的类型,但是转换结果一定是一个原始值(或者报错)。

1.1如果PreferredType被标记为Number,则会进行下面的操作流程来转换输入的值。

1、如果输入的值已经是一个原始值,则直接返回它2、否则,如果输入的值是一个对象,则调用该对象的valueOf()方法,   如果valueOf()方法的返回值是一个原始值,则返回这个原始值。3、否则,调用这个对象的toString()方法,如果toString()方法返回的是一个原始值,则返回这个原始值。4、否则,抛出TypeError异常。复制代码

1.2如果PreferredType被标记为String,则会进行下面的操作流程来转换输入的值。

1、如果输入的值已经是一个原始值,则直接返回它2、否则,调用这个对象的toString()方法,如果toString()方法返回的是一个原始值,则返回这个原始值。3、否则,如果输入的值是一个对象,则调用该对象的valueOf()方法,   如果valueOf()方法的返回值是一个原始值,则返回这个原始值。4、否则,抛出TypeError异常。复制代码

既然PreferredType是可选参数,那么如果没有这个参数时,怎么转换呢?PreferredType的值会按照这样的规则来自动设置:

1、该对象为Date类型,则PreferredType被设置为String2、否则,PreferredType被设置为Number复制代码

toString()valueOf() 的用法有待补充。

2.ToNumber()

根据参数类型进行下面转换:

参数 结果
undefined NaN
null +0
布尔值 true转换1,false转换为+0
数字 无须转换
字符串 有字符串解析为数字,例如:‘324’转换为324,‘qwer’转换为NaN
对象 先进行 ToPrimitive(obj, Number)转换得到原始值,在进行ToNumber转换为数字

3.ToString()

根据参数类型进行下面转换:

参数 结果
undefined 'undefined'
null 'null'
布尔值 转换为'true' 或 'false'
数字 数字转换字符串,比如:1.765转为'1.765'
字符串 无须转换
对象 先进行 ToPrimitive(obj, String)转换得到原始值,在进行ToString转换为字符串

Object.is():

Object.is() 判断两个值是否相同。如果下列任何一项成立,则两个值相同:

  • 两个值都是 undefined
  • 两个值都是 null
  • 两个值都是 true 或者都是 false
  • 两个值是由相同个数的字符按照相同的顺序组成的字符串
  • 两个值指向同一个对象
  • 两个值都是数字并且
  • 都是正零 +0
  • 都是负零 -0
  • 都是 NaN
  • 都是除零和 NaN 外的其它同一个数字

这种相等性判断逻辑和传统的 ==运算符所用的不同,==运算符会对它两边的操作数做隐式类型转换(如果它们类型不同),然后才进行相等性比较,(所以才会有类似 "" == falsetrue 的现象),但 Object.is 不会做这种类型转换。

这与===运算符也不一样。===运算符(和==运算符)将数字值-0+0视为相等,并认为Number.NaN不等于NaN。 示例:

Object.is('foo', 'foo');     // trueObject.is(window, window);   // trueObject.is('foo', 'bar');     // falseObject.is([], []);           // falsevar test = { a: 1 };Object.is(test, test);       // trueObject.is(null, null);       // true// 特例Object.is(0, -0);            // falseObject.is(-0, -0);           // trueObject.is(NaN, 0/0);         // true复制代码

实际运用

我们先看以下以下几种值比较的结果:

挑选重点来分析如下:

[1,2] == "1,2" //true复制代码

左边数组类型为Obeject,右边是String,满足总结条件6。 执行ToPrimitive([1,2]),在没有参数的情况下且不为Date类型,转换类型自动为Number 再执行 [1,2].valueOf(),类型还是Obeject,不为原始值 再执行[1,2].toString()"1,2" 为字符串原始值 最后比较"1,2" == "1,2",返回true

开始的那个问题:

null == false; //false复制代码

因为false是Boolean类型,满足总结中的第五条,所以实际比较

Number(bull) == false;0 == null;//false复制代码

最新的 ECMAScript 标准定义了 7 种数据类型: 6 种 原始类型: Boolean Null Undefined Number String Symbol (ECMAScript 6 新定义) 和 Object

0 == null null的类型是Null,实际上这个比较不满足转换的任何一条规则,所以返回false

0 == NaN; //false复制代码

两边都是Number类型,所以比较全等=== 返回false

NaN == NaN; //false复制代码

从数值的角度上讲NaN不与任何值相等。

转载地址:http://bfmja.baihongyu.com/

你可能感兴趣的文章
weblogic多池与oracle集群RAC
查看>>
php类库安装xml simplexml
查看>>
Asp.Net SignalR Hub集线器
查看>>
关于集成抽取进程重启后的现象分析
查看>>
56.如何清除已经设置的npm config配置
查看>>
028——VUE中事件修饰符once
查看>>
FineUIPro v5.1.0 发布了!
查看>>
easyui的日期控件
查看>>
[WPF 容易忽视的细节] —— Exception in WPF's Converter
查看>>
网易严选的wkwebview测试之路
查看>>
Dubbo高可用
查看>>
折叠代码块 C#中用 #region和#endregion java中用 //region和//endregion
查看>>
高性能mysql学习笔记
查看>>
[ffmpeg] 音频样本
查看>>
jQuery 3D圆盘旋转焦点图 支持鼠标滚轮
查看>>
非常实用全面的 C++框架,库类等资源
查看>>
VS Code 常用插件
查看>>
kubectl top查看k8s pod的cpu , memory使用率情况
查看>>
fputs
查看>>
手写代码生成器
查看>>