Javascript比较的艺术

作者: lanzhiheng | 来源:发表于2016-07-23 00:52 被阅读100次

    我们该如何比较?

    1.两个对象的比较

    Javascript的比较中参杂了一些比较奇怪的特性,我们来看一些比较简单的比较。

    // 原始值的比较
    > var a = 12
    undefined
    > var b = 12
    undefined
    > a == b
    true
    > a === b
    true
    // 对象的比较
    > var c = []
    undefined
    > var d = []
    undefined
    > c == d
    false
    > c === d
    false
    

    由上面的结果可以看出比较两个原始值跟比较对象规则似乎有点不同,比较两个对象值的话即便它们的相同,但是最后的结果是不一样的。比较两个对象,应该比较的是两个对象的引用

    如果我们这样操作:

    > var m = {}
    undefined
    > n = m
    {}
    > n === m
    true
    

    表示两个变量都指向同一个对象,所以它们就是相同的了。

    2.不同类型的比较

    还有下面这个比较特殊的情况

    > 12 == "12"
    true
    
    > null == undefined
    true
    > undefined == false
    false
    > null == false
    false
    > null === undefined
    false
    

    为什么整型能够等于字符串?这是由于==(等于而非全等)并不比较类型,它比较之前会将需要比较的值进行类型转换,这里的话会将字符串转换成数值类型然后进行比较。为什么这么肯定? 我们做一下实验。

    > 1 + 2
    3
    > 1 + "2"
    '12'
    > 2 < "12"
    true
    > "2" < "12"
    false
    

    从上面例子可以看出,数值2确实是比字符串12小的。如果比较之前是数值转换成字符串那结果应该是"2" > "12"才对。
    还不相信?我再举个例子。

    > "12d" > 12
    false
    > "12d" < 12
    false
    > "12d" == 12
    false
    > "12" < "12d"
    true
    

    这不是日了狗了?如果是将12转换成字符串的话,那12d应该是大于12才对吧。为什么怎么比较都是false?我估计是由于下面这个特殊的家伙。

    > NaN < 1
    false
    > NaN > 1
    false
    

    NaN无论跟什么进行比较,都会返回false。包括它自己。所以要判断一个变量是不是NaN最好的办法就是x != x如果返回的是true则表明x是NaN。那么这里应该就是当12d要转换成数值类型的时候由于带有特殊的字符,最后变成了NaN了,跟数值类型无论怎么比较结果都是false

    对于数字与字符串操作符来说,加号运算符跟比较运算符的行为有所不同。加号运算符更偏爱字符串,如果其中一个操作数是字符串的话则会转换成字符串。而比较运算符则比较偏爱数字,只有在两个数字都为字符串的时候才会进行字符串比较。

    至于上面的nullundefined。。。。。我暂时也不知道怎么解释它们的行为。我也只能姑且记住。因为它们比较特殊

    3.对象跟原始值的比较

    如果两个需要比较的对象一个是javascript对象一个是字符串,则会进行某种程度上的类型转换。想办法把对象的值转换成原始值。一般来说就有valueOf, toString两种方法。下面是一个空对象的转换流程:

    
    // 我直接明文写出来了
    > a = {}
    {}
    // 1. valueOf 转换
    > a.valueOf()
    {}
    
    // 2. 如果上面操作得到的不是一个原始值则进而用toString 转换。(反之亦然)
    > a.toString()
    '[object Object]'
    > a == '[object Object]'
    true
    

    上面其实是一个内置对象的转换过程,也是javascript的机制。首先它会调用valueOf进行转换,如果得到的值并不是一个原始值,则会进而调用toString进行转换,最后得到的值是'[object Object]'一个很奇怪的值,不过它是原始值。如果把变量a跟这个值做相等判断(不是全等)则可以得出一个true的结果。(是不是被它搞崩溃了?)

    然而权威指南给了如下原则,我们可以参考一下。

    原始值的转换JavaScript语言核心内置类首先尝试使用ValueOf转换,然后使用toString进行转换。除了日期类,它只使用toString进行转换。那些不是JavaScript核心中的对象则通过各自的实现中定义的方式来转换为原始值。

    根据上面的解释。我们的a={}与原始值进行比较的时候,会先调用valueOf函数,它的结果是{}显然不是一个原始值。则会使用toString进行转换。最后得出了那个很奇怪的结果。不过这个很奇怪的结果'[object Object]'确实是 {}的原始值。(它是字符串的字面量)。

    -_-我看这些也很费解。不过最后还是说一句

    Happy Coding !! _

    相关文章

      网友评论

        本文标题:Javascript比较的艺术

        本文链接:https://www.haomeiwen.com/subject/xtzijttx.html