你的位置:首页 > 软件开发 > Java > 对于JS == 运算的一些理解

对于JS == 运算的一些理解

发布时间:2016-10-07 13:00:09
声明:本文是摘自一篇文章,放在这只为做为一个笔记能更好学习。 大家知道,==是JavaScript中比较复杂的一个运算符。它的运算规则奇怪,容易让人犯错,从而成为JavaScript中“最糟糕的特性”之一。 在仔细阅读了ECMASc ...

对于JS == 运算的一些理解

声明:本文是摘自一篇文章,放在这只为做为一个笔记能更好学习。

 

对于JS == 运算的一些理解

家知道,==是JavaScript中比较复杂的一个运算符。它的运算规则奇怪,容易让人犯错,从而成为JavaScript中“最糟糕的特性”之一。

 

在仔细阅读了ECMAScript规范的基础上,画了一张图,通过它你会彻底地搞清楚关于==的一切。同时,试图通过此文向大家证明==并不是那么糟糕的东西,它很容易掌握,甚至看起来很合理。

 

先上图:

对于JS == 运算的一些理解

图1 ==运算规则的图形化表示

 

==运算规则的精确描述在此:The Abstract Equality Comparison Algorithm(http://es5.github.io/#x11.9.3)。但是,这么复杂的描述,你确定看完后脑子不晕?确定立马就能拿它指导实践?

 

肯定不行,规范毕竟是给JavaScript运行环境的开发人员看的(比如V8引擎的开发人员们),而不是给语言的使用者看的。而上图正是将规范中复杂的描述翻译成了更容易看懂的形式。

 

在详细介绍图1中的每个部分前,我们来复习一下JS中关于类型的知识:

  1. JS中的值有两种类型:原始类型(Primitive)、对象类型(Object)。

  2. 原始类型包括:Undefined、Null、Boolean、Number和String等五种。

  3. Undefined类型和Null类型的都只有一个值,即undefined和null;Boolean类型有两个值:true和false;Number类型的值有很多很多;String类型的值理论上有无数个。

  4. 所有对象都有valueOf()和toString()方法,它们继承自Object,当然也可能被子类重写。

现在考虑表达式

x == y

其中x和y是上述六种类型中某一种类型的值。

 

当x和y的类型相同时,x == y可以转化为x === y,而后者是很简单的(唯一需要注意的可能是NaN),所以下面我们只考虑x和y的类型不同的情况。

 

 1   有和无

 

在图1中,JavaScript值的六种类型用蓝底色的矩形表示。它们首先被分成了两组:

  • String、Number、Boolean和Object (对应左侧的大矩形框)

  • Undefined和Null (对应右侧的矩形框)

 

分组的依据是什么?我们来看一下,右侧的Undefined和Null是用来表示不确定或者的,而右侧的四种类型都是确定的非空。我们可以这样说:

左侧是一个存在的世界,右侧是一个的世界。

所以,左右两个世界中的任意值做==比较的结果都是false是很合理的。(见图1中连接两个矩形的水平线上标的false)

 

 2   空和空

 

JavaScript中的undefined和null是另一个经常让我们崩溃的地方。通常它被认为是一个设计缺陷,这一点我们不去深究。不过我曾听说,JavaScript的作者最初是这样想的:

假如你打算把一个变量赋予对象类型的值,但是现在还没有赋值,那么你可以用null表示此时的状态(证据之一就是typeof null 的结果是'object');相反,假如你打算把一个变量赋予原始类型的值,但是现在还没有赋值,那么你可以用undefined表示此时的状态。

不管这个传闻是否可信,它们两者做==比较的结果是true是很合理的。(见图1中右侧垂直线上标的true)

在进行下一步之前,我们先来说一下图1中的两个符号:大写字母N和P。这两个符号并不是PN结中正和负的意思。而是:

  • N表示ToNumber操作,即将操作数转为数字。它是规范中的抽象操作,但我们可以用JS中的Number()函数来等价替代。

  • P表示ToPrimitive操作,即将操作数转为原始类型的值。它也是规范中的抽象操作,同样也可以翻译成等价的JS代码。不过稍微复杂一些,简单说来,对于一个对象obj:

ToPrimitive(obj)等价于:先计算obj.valueOf(),如果结果为原始值,则返回此结果;否则,计算obj.toString(),如果结果是原始值,则返回此结果;否则,抛出异常。

注:此处有个例外,即Date类型的对象,它会先调用toString()方法,后调用valueOf()方法。

 

在图1中,标有N或P的线表示:当它连接的两种类型的数据做==运算时,标有N或P的那一边的操作数要先执行ToNumber或ToPrimitive变换。

 

 3   真与假

 

从图1可以看出,当布尔值与其他类型的值作比较时,布尔值会转化为数字,具体来说

true -> 

原标题:对于JS == 运算的一些理解

关键词:JS

JS
*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。