最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 什么!?a == 'juejin' && a == 666 && a == 888 为true?

    正文概述 掘金(梨香)   2021-06-20   657

    看到这个标题,很多人可能会感觉很新奇, a == 'juejin' && a == 666 && a == 888 为 true,这怎么可能呢?javascript 有时就是这么的神奇,上面表达式的实现是通过 js 隐式转换部分知识实现的,那让我们先来了解一下隐式转换,再去尝试实现上述表达式吧。

    什么是隐式转换

    在 javascript 中,当运算符在运算时,如果两边数据类型不统一,CPU就无法进行运算,这时 javascript 会自动将运算符两边的数据做一个数据类型转换,转成一样的数据类型再计算。这种无需程序员手动转换,而由编译器自动转换的方式就称为隐式转换。

    当引用类型和基础类型进行运算时,会将引用类型转换为基础类型。在 javascript 中,每个引用类型都有他们的内置方法,其中有两个内置方法 valueOf()toString():

    • toString(): 返回对象的字符串表示。
    • valueOf(): 返回对象对应的字符串、数值或布尔值表示。通常与 toString()的返回值相同。

    他们能够将 Object 类型隐式转换为基础类型,从而进行运算和比较。

    不同类型转换规则

    了解了隐式转换需要将不同类型转换为同一类型,那我们需要在了解一下不同类型转换的规则。

    首先 js 目前有基本类型: number、string、boolean、undefined、null和symbol,引用类型为Object。

    其中,js规定 undefined == null,且其他类型无法转换为 undefined 和 null。剩下的其他类型大多可以互相转化。

    其他类型 -> number类型

    string -> number

    • 如果 string 的内容为纯数字内容,则转换结果为数字
    • 如果 string 的内容不是纯数字,则转换结果为NaN
    Number('1272421')  // 1272421
    Number('ok111')    // NaN
    

    boolean -> number

    • true -> 1
    • false -> 0
    Number(true)   // 1
    Number(false)  // 0
    

    undefined -> number

    • undefined -> NaN
    Number(undefined)   // NaN
    

    null -> number

    • null -> 0
    Number(null)   // 0
    

    Object -> number

    • 先调用 valueOf() 方法,看能否得到一个基础类型,如能,使用 Number() 对此基础类型进行转换
    • 如调用 valueOf() 没有得到基础类型,则调用 toString() 方法看能否得到一个基础类型,如能,使用 Number() 对此基础类型进行转换;如不能,报错
    // 未实现自定义 valueOf() 和 toString() 的对象
    const a = { value: 1 }
    Number(a)  // NaN
    // 自定义了 valueOf() 返回基础类型
    const b = {
        valueOf() {
            return 6
        }
    }
    Number(b)  // 6
    // 自定义了 toString() 返回基础类型
    const c = {
        toString() {
            return 7
        }
    }
    Number(c)  // 7
    // 自定义了 valueOf() 和 toString() 都不返回基础类型
    const d = {
        valueOf() {
            return {}
        },
        toString() {
            return {}
        }
    }
    Number(d)  // Uncaught TypeError: Cannot convert object to primitive value
    

    其他类型 -> string

    基础类型 -> string

    • 基础类型转换为string,相当于直接在外面""变成字符串内容
    String(666)   // "666"
    String(true)  // "true"
    String(undefined)  // "undefined"
    String(null) // "null"
    

    Object -> string

    • 先调用 toString() 方法,看能否得到一个基础类型,如能,使用 String() 对此基础类型进行转换
    • 如调用 toString() 没有得到基础类型,则调用 valueOf() 方法看能否得到一个基础类型,如能,使用 String() 对此基础类型进行转换;如不能,报错
    // 未实现自定义 valueOf() 和 toString() 的对象
    const a = { value: 1 }
    Number(a)  // "[object Object]"
    // 自定义了 toString() 返回基础类型
    const b = {
        valueOf() {
            return "ok"
        }
    }
    String(b)  // "ok"
    // 自定义了 valueOf() 返回基础类型
    const c = {
        toString() {
            return "hello"
        }
    }
    String(c)  // "hello"
    // 自定义了 valueOf() 和 toString() 都不返回基础类型
    const d = {
        valueOf() {
            return {}
        },
        toString() {
            return {}
        }
    }
    String(d)  // Uncaught TypeError: Cannot convert object to primitive value
    

    其他类型 -> boolean

    • undefined null 0 -0 +0 NaN '' 转换结果为 false
    • 其他类型和值转换结果都为 true
    Boolean(undefined) // false
    Boolean({}) // true
    

    == 比较规则

    基础类型的比较

    • undefined等于null
    • string 和 number 比较时,string 转 number
    • number 和 boolean 比较时,boolean 转 number
    • string 和 boolean 比较时,两者转 number
    undefined == null;    //true
    '0' == 0;            //true,字符串转数字
    0 == false;           //true,布尔转数字
    '0' == false;       //true,两者转数字
    

    引用类型和基础类型比较

    引用类型和基础类型比较,上面提到过会通过 valueOf() 和 toString() 方法将引用类型转换为基础类型,然后进行比较。上面有提到过转换规则,引用类型转换为 number 类型优先使用 valueOf(),转换成 string 类型优先使用 toString()。

    但是在使用 == 进行比较时有一点区别:

    • 和 boolean 类型比较,都转换为 true
    • 和 number 或者 string 类型比较,都优先使用 valueOf() 看能否转换为基础类型,能的话将基础类型在转换成对应的 number 或者 string 类型比较;不能的话再使用 toString() 进行转换

    实现 a == 'juejin' && a == 666 && a == 888

    理解了上面的隐式转换规则,那我们就可以思考如何来实现了。

    我们可以自定义 valueOf(),第一次比较时返回的值为 'juejin',第二次为666,之后返回的值为888:

    const a = {
     count: 0, // 记录当前是第几次比较
     valueOf() {
       this.count++;
       if(this.count === 1) {
         return 'juejin'
       } else if(this.count === 2) {
         return 666
       } else {
         return 888
       }
     }
    }
    
    console.log(a == 'juejin' && a == 666 && a == 888)  // true
    

    如此就实现了标题中的表达式为 true。


    起源地下载网 » 什么!?a == 'juejin' && a == 666 && a == 888 为true?

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元