UDN-企业互联网技术人气社区

板块导航

浏览  : 1370
回复  : 2

[原生js] 在JavaScript中什么时候使用==是正确的?

[复制链接]
cat77的头像 楼主
发表于 2015-9-1 16:13:07 | 显示全部楼层 |阅读模式
  在JavaScript中什么情况下使用==是正确的?简而言之:没有。这篇文章来看五种情况下总是使用===,并且解释为什么不用==。

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

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

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

  意图清晰的代码胜过更简洁的代码。 记住:你的代码仅写一次,但被阅读很多次——尽可能保证对阅读者友好。

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

  例如,使用typeof操作符[2],你能确保结果是字符串。然后可以放心使用 ==,因为我们确定不会在发生类型转换。
  1. if (typeof x == "function") {
  2.         ...
  3. }
复制代码

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

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

  例2:与undefined和null做比较

  当使用 == 时,undefined和null在结果上等价——他们彼此相等,互相相等,但没有意义(包括JavaScript中的能被转换为false的值):
  1. > null == null
  2. true
  3. > undefined == null
  4. true
  5. > false == null
  6. false
  7. > 0 == null
  8. false
复制代码

  因此,下面的if语句检测的是null或undefined。
  1. if (x == null) {
  2.     ...
  3. }
复制代码

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

  如果你有点懒的话,上面的代码能被精简为:
  1. if (!x) {
  2.     ...
  3. }
复制代码

  和上面一样的警告:这条件成立,如果x有否定类型的值。
  1. undefined
  2. null
  3. false
  4. 0
  5. ""
复制代码

  例3:比较字符串和数字

  场景:你正工作在用户界面代码或编码处理服务器端参数。你可能会把数字编码为字符串。如果x是一个字符串,你可以像下面这样比较:
  1. if (x == 123) {
  2.     ...
  3. }
复制代码

  但问什么不告诉其他阅读你代码的人,如果x不是数字,它将被转换为数字?
  1. if (Number(x) === 123) {
  2.     ...
  3. }
复制代码

  例4:比较对象和原始值

  使用 == 时你可以将一个原始值和其他原始值或包装类型 [4]实例做比较:
  1. > function isAbc(x) { return x == "abc" }
  2. > isAbc("abc")
  3. true
  4. > isAbc(new String("abc"))
  5. true
复制代码

  而使用 === 时,你不能这样做:
  1. > new String("abc") === "abc"
  2. false
复制代码

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

  你的目的是什么?

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

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

  理由是这样的:我想我的代码像JavaScript一样灵活。== 操作符帮我实现这一目的。例如JavaScript的灵活体现在它自动转换值类型:
  1. > "abc" + false
  2. 'abcfalse'
  3. > 3 + true
  4. 4
  5. > +"73"
  6. 73
复制代码

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

  1.即使会自动转换但并不总是按你需要的方式转换。例如:
  1. > !"false"
  2. false
  3. > 7 + "3"
  4. '73'
  5. > Number("")
  6. 0
复制代码

  2.非严格相等的转换规则非常复杂:
  1. > 2 == false
  2. false
  3. > 2 == true
  4. false
  5. > Boolean(2)
  6. true
复制代码

  3.显示转化加上严格相等的代码更具描述性。比较:灵活的非严格相等。
  1. function is123Implicit(x) {
  2.     return x == 123;
  3. }
  4. > is123Implicit(123)
  5. true
  6. > is123Implicit(new Number(123))
  7. true
  8. > is123Implicit("123")
  9. true
复制代码

  替代方案:灵活的显式转换和严格相等。
  1. function is123Explicit(x) {
  2.     x = Number(x);
  3.     return x === 123;
  4. }
  5. > is123Explicit(123)
  6. true
  7. > is123Explicit(new Number(123))
  8. true
  9. > is123Explicit("123")
  10. true
复制代码

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

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

  结论

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

相关帖子

发表于 2015-9-1 16:13:30 | 显示全部楼层
使用道具 举报

回复

发表于 2015-9-18 14:05:46 来自手机 | 显示全部楼层
回帖支持下楼主,请眼熟我,我叫“不帅“
使用道具 举报

回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部