在JavaScript中什么情况下使用==是正确的?简而言之:没有。这篇文章来看五种情况下总是使用===,并且解释为什么不用==。

JavaScript有两种操作符用来比较两个值是否相等 [1]

  • 严格相等 === 仅考虑相同类型的值是否相等。
  • “正常”(或非严格)相等操作符 == 在比较之前,尝试为不同类型的值进行转换,然后类似严格相等。

给JavaScript初学者的建议是完全忘掉 == ,并且总是使用 ===。事实证明,后者是更符合常规的。有五种案例,表面看起来可以不遵从规则,但真的不是这样。从现在开始,我使用下面的规则:

意图清晰的代码胜过更简洁的代码。

记住:你的代码仅写一次,但被阅读很多次——尽可能保证对阅读者友好。

例1:你清楚自己在比较什么

例如,使用typeof操作符[2],你能确保结果是字符串。然后可以放心使用 ==,因为我们确定不会在发生类型转换。

if (typeof x == "function") {
...
}

然而,有两个反对这样做的原因:

  • 一致性:使用==对一致性没有任何好处,那么为什么不避免使用呢?
  • 简单和性能:一般来说,=== 是最简单的操作符,因为它不进行类型转换。JavaScript引擎的性能参差不齐[3],但在大部分浏览器中 === 比 == 速度更快。

例2:与undefined和null做比较

当使用 == 时,undefined和null在结果上等价——他们彼此相等,互相相等,但没有意义(包括JavaScript中的能被转换为false的值):

    > null == null
true
> undefined == null
true
> false == null
false
> 0 == null
false

因此,下面的if语句检测的是null或undefined。

    if (x == null) {
...
}

然而,这是否出于简洁性考虑,意图并不清晰:如果你同时也检测undefined,那么你可以这样写。然而,如果JavaScript初学者读到你的代码,他们可能认为你仅仅检测null。如果高手读到你的代码,他们可能认为你写错了,并且应该写成 ===。

    if (x === undefined || x === null) {
...
}

如果你有点懒的话,上面的代码能被精简为:

    if (!x) {
...
}

和上面一样的警告:这条件成立,如果x有否定类型的值。

    undefined
null
false
0
""

例3:比较字符串和数字

场景:你正工作在用户界面代码或编码处理服务器端参数。你可能会把数字编码为字符串。如果x是一个字符串,你可以像下面这样比较:

    if (x == 123) {
...
}

但问什么不告诉其他阅读你代码的人,如果x不是数字,它将被转换为数字?

    if (Number(x) === 123) {
...
}

例4:比较对象和原始值

使用 == 时你可以将一个原始值和其他原始值或包装类型 [4]实例做比较:

    > function isAbc(x) { return x == "abc" }
> isAbc("abc")
true
> isAbc(new String("abc"))
true

而使用 === 时,你不能这样做:

    > new String("abc") === "abc"
false

左边是一个对象而右边是原始值。因为他们类型不同所以不严格相等。然而,你同样需要向阅读你代码的人解释清楚你的意图。下面是表达式:

 x == "abc"

你的目的是什么?

  • 你真的想让一个包装字符串和右边的字符串作比较吗?这似乎不太可能,但如果确实是这样,你应该小心翼翼并给出文档记录。
  • 你想将x转换为字符串?那应该写的更明确
    String(x) === "abc"
  • 你想提取包装变量的原始值?那你应该考虑下面的写法
     x.valueOf() === "abc"

例5:JavaScript是灵活的语言——我的代码也应该这样

理由是这样的:我想我的代码像JavaScript一样灵活。== 操作符帮我实现这一目的。例如JavaScript的灵活体现在它自动转换值类型:

    > "abc" + false
'abcfalse'
> 3 + true
4
> +"73"
73

有几个理由反驳上述假说:

  • 即使会自动转换但并不总是按你需要的方式转换。例如:
  •     > !"false"
    false
    > 7 + "3"
    '73'
    > Number("")
    0
  • 非严格相等的转换规则非常复杂:
        > 2 == false
    false
    > 2 == true
    false
    > Boolean(2)
    true
  • 显示转化加上严格相等的代码更具描述性。比较:灵活的非严格相等。
    function is123Implicit(x) {
    return x == 123;
    }
    > is123Implicit(123)
    true
    > is123Implicit(new Number(123))
    true
    > is123Implicit("123")
    true

    替代方案:灵活的显式转换和严格相等。

    function is123Explicit(x) {
    x = Number(x);
    return x === 123;
    }
    > is123Explicit(123)
    true
    > is123Explicit(new Number(123))
    true
    > is123Explicit("123")
    true
  • 有人说您的代码缺少灵活性?可以说JavaScript的默认灵活性利大于弊(对于学习难度而言)。写防御型的代码更容易暴漏Bug。is123Explicit() 的防御型版本看起来像下面这样:
    function is123Defensive(x) {
    if (typeof x !== "number") {
    throw new TypeError("Not a number: "+x);
    }
    return x === 123;
    }

    如果你想给函数传递任何非原始数字值,你必须先进行类型转换。

结论

我希望我让你确信坚持简单的规则——”不用 ==“的意义,不只是对新手。在你的代码中魔法越少,通常意味着越容易理解。

相关阅读

  1. Equality in JavaScript: === versus ==
  2. Improving the JavaScript typeof operator
  3. jsPerf: == versus ===
  4. JavaScript values: not everything is an object

相关阅读

英文:http://www.2ality.com/2011/12/strict-equality-exemptions.html

Q群推荐

CSS家园 188275051,Web开发者(前后端)的天堂,欢迎有兴趣的同学加入

GitHub家园 225932282,Git/GitHub爱好者的天堂,欢迎有兴趣的同学加入

码农之家 203145707,码农们的天堂,欢迎有兴趣的同学加入

在JavaScript中什么时候使用==是正确的?的更多相关文章

  1. Javascript中判断数组的正确姿势

    在 Javascript 中,如何判断一个变量是否是数组? 最好的方式是用 ES5 提供的 Array.isArray() 方法(毕竟原生的才是最屌的): var a = [0, 1, 2]; con ...

  2. 正确理解JavaScript中的this关键字

    JavaScript有this关键字,this跟JavaScript的执行上下文密切相关,很多前端开发工程师至今对this关键字还是模棱两可,本文将结合代码讲解下JavaScript的this关键字. ...

  3. JavaScript中错误正确处理方式,你用对了吗?

    JavaScript的事件驱动范式增添了丰富的语言,也是让使用JavaScript编程变得更加多样化.如果将浏览器设想为JavaScript的事件驱动工具,那么当错误发生时,某个事件就会被抛出.理论上 ...

  4. JavaScript中Array的正确使用方式

    在 JavaScript 中正确使用地使用 Array 的方法如下: 用 Array.includes 代替 Array.indexOf “如果你要在数组中查找元素,请使用 Array.indexOf ...

  5. javascript中的正确错误处理------------引用

    JavaScript的事件驱动机制让JavaScript更加丰富,浏览器好比就是一个事件驱动的机器,错误也是一种事件.当一个错误发生时,一个事件就在某个点抛出. 解释起来就是,当发生错误时,JavaS ...

  6. 如何在JavaScript中正确引用某个方法(bind方法的应用)

    在JavaScript中,方法往往涉及到上下文,也就是this,因此往往不能直接引用,就拿最常见的console.log("info…")来说,避免书写冗长的console,直接用 ...

  7. javascript中判断变量是否存在的正确方式

    在Javascript中,我们通常判断一个变量是否存在(即不为null或者undefined),往往是这样判断的 if(tomy){ console.log(obj.name); } 这种写法在大部分 ...

  8. javascript中的Array对象 —— 数组的合并、转换、迭代、排序、堆栈

    Array 是javascript中经常用到的数据类型.javascript 的数组其他语言中数组的最大的区别是其每个数组项都可以保存任何类型的数据.本文主要讨论javascript中数组的声明.转换 ...

  9. JavaScript 中的数据类型

    Javascript中的数据类型有以下几种情况: 基本类型:string,number,boolean 特殊类型:undefined,null 引用类型:Object,Function,Date,Ar ...

随机推荐

  1. 【整理】HTML5游戏开发学习笔记(3)- 抛物线运动

    1.预备知识(1)Canvas旋转的实现过程 window.onload = function(){ var ctx = document.getElementById('canvas1').getC ...

  2. 第10月第1天 iOS crash

    1. find /Applications/Xcode6.1.app -name symbolicatecrash -type f tempdeMac-mini:crash temp$ dwarfdu ...

  3. MongoDB 之 Limit 选取 Skip 跳过 Sort 排序 MongoDB - 7

    我们已经学过MongoDB的 find() 查询功能了,在关系型数据库中的选取(limit),排序(sort) MongoDB中同样有,而且使用起来更是简单 首先我们看下添加几条Document进来 ...

  4. git使用常用命令

    第一部分:个人整理部分(读<Git教程By廖雪峰.pdf>笔记) /* 配置全局参数 */git config --global user.name "username" ...

  5. [转]使用 mitmproxy + python 做拦截代理

    使用 mitmproxy + python 做拦截代理   本文是一个较为完整的 mitmproxy 教程,侧重于介绍如何开发拦截脚本,帮助读者能够快速得到一个自定义的代理工具. 本文假设读者有基本的 ...

  6. C#使用mybatis学习笔记

    1.官网:http://mybatis.org/index.html 2.代码:https://code.google.com/p/mybatisnet/ 3.wiki:http://zh.wikip ...

  7. Project Euler Problem1

    Multiples of 3 and 5 Problem 1 If we list all the natural numbers below 10 that are multiples of 3 o ...

  8. 六、vue路由Vue Router

    一.基本概念 route, routes, router 1, route,它是一条路由,由这个英文单词也可以看出来,它是单数, Home按钮  => home内容, 这是一条route,  a ...

  9. ASP.NET MVC 路由学习

    参考 http://www.cnblogs.com/yaozhenfa/p/asp_net_mvc_route_2.html 说明 1."解决与物理路径的冲突"这段教程这里如果不起 ...

  10. 【Unity_UWP】Unity 工程发布win10 UWP 时的本地文件读取 (下篇)

    Universal Windows Platform(UWP)是微软Windows10专用的通用应用平台,其目的在于在统一操作系统下控制所有智能电子设备. 自从Unity 5.2之后,配合VS 201 ...