• js 隐式转换


    一、ToPrimitive内部运算

    1.定义

    ToPrimitive运算,它会用于对象转换为原始数据类型,这个运算不只会用在加号运算符,也会用在关系比较或值相等比较的运算中。

    语法:ToPrimitive(input, PreferredType?)

    input代表代入的值,而PreferredType可以是数字(Number)或字符串(String)其中一种,没有PreferredType默认为数字(Number)。如果input为原始值,则返回原始值;如果为对象,则转换如下:

    2.PreferredType为数字(Number)

    1).调用对象的valueOf()方法,如果能得到原始数据类型的值,则返回这个值。
    2).调用对象的toString()方法,如果能得到原始数据类型的值,则返回这个值。
    3).否则,抛出TypeError错误。

    3.PreferredType为数字(String)

    1).调用对象的toString()方法,如果能得到原始数据类型的值,则返回这个值。
    2).调用对象的valueOf()方法,如果能得到原始数据类型的值,则返回这个值。
    3).否则,抛出TypeError错误。

    4.实例

    1)字符串 + 其他原始类型

    字符串在加号运算有最高的优先运算,与字符串相加必定是字符串连接运算。所有的其他原始数据类型转为字符串

    2)数字 + 其他的非字符串的原始数据类型

    数字与其他类型作相加时,除了字符串会优先使用字符串连接运算的,其他都要依照数字为优先,所以除了字符串之外的其他原始数据类型,都要转换为数字来进行数学的相加运算。

    3)数字/字符串以外的原始数据类型作加法运算

    当数字与字符串以外的,其他原始数据类型直接使用加号运算时,就是转为数字再运算,这与字符串完全无关。

    4)[] + []

    数组会调用valueOf和toString方法,[] + [] => '"" + ""  = ""得到空字符串

    5){} + {}

    在谷歌浏览器上,{}会调用 valueOf和toString方法得到“[object Object]”,两个相加便得到"[object Object][object Object]"

    在Firefox、Edge浏览器则不同,会把前面的{}当做区块语句,略过,剩下+{},进行Number({})运算,相当于Number("[object Object]")运算,最后得出的是NaN

    6){} + []

    浏览器把{}当做区块语句略过,剩下+[],相当于进行Number([])运算,Number("") => 0

    7)[] + {}

    相当于"" + "[object Object]" => "[object Object]"

    8)Date对象

    Date对象调用valueOf和toString方法有些不同(一般对象会先调用valueOf再调用toString),Date对象会先调用toString再调用valueOf

    二、++[[]][+[]]+[+[]] == 10

    首先将++[[]][+[]]+[+[]] 分解为++[[]][+[]] 和 [+[]] 

    1.[+[]]

    +[],[]是对象,进行toPrimitive运算,调用valueOf方法得到[]不是原始值,然后调用toString方法得到空字符串,转换为数字后得到0,那么[+[]]等于[0]

    2.++[[]][+[]]

    将++[[]][+[]]变为
    var val = [[]][+[]];

    ++val;

    根据上面得出,[+[]]为0,[[]][+[]] => [[]][0] => []

    进一步拆分

    var val = [];

    ++val;

    因为++时候旧的值要进行 ToNumber() 运算(ToNumber把其他类型按照一定的规则转化成数字类型,也就是类似Number())

    所以++val 相当于 val = ToNumber([]) + 1 => 0 + 1 => 1

    3.++[[]][+[]]+[+[]]

    ++[[]][+[]]+[+[]] => 1 + [0] => 1 + "0" => "10"

    所以++[[]][+[]]+[+[]]  == 10

    三、用隐式转换输出"I love you"

    (+!![]/+[]+[])[+[]]+([]+{})[~!![]*~!![]*-~!![]-!![]]+(![]+[])[-~!![]]+([]+{})[+!![]]+([][(![]+[])[!![]-~!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]]+[])[[]+(+!![]+!![])+(!![]-~!![])]+(!![]+[])[!![]-~!![]]+([]+{})[~!![]*~!![]*-~!![]-!![]]+(+!![]/+[]+[])[-~-~-~-~-~-~!!{}]+([]+{})[+!![]]+(!![]+[])[-~!![]]

    转换步骤:

    I:(+!![]/+[]+[])[+[]] // 1/0得到 Infinity,加上[]得到"Infinity","Infinity"[0] => "I"

    " ": ([]+{})[~!![]*~!![]*-~!![]-!![]] // [] + {} => "[object Object]", "[object Object]"[7] => " "

    l:(![]+[])[-~!![]] // "false"[2] => "l"

    o: ([]+{})[+!![]] // "[object Object]", "[object Object]"[1] => "o"

    v:([][(![]+[])[!![]-~!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]]+[])[[]+(+!![]+!![])+(!![]-~!![])] 
    1) []['sort']+[] => "function sort() { [native code] }"
    2) "function sort() { [native code] }"[23] => "v"

    e:(!![]+[])[!![]-~!![]] // "true"[3] => "e"

    " " : ([]+{})[~!![]*~!![]*-~!![]-!![]] // [] + {} => "[object Object]", "[object Object]"[7] => " "
    y:(+!![]/+[]+[])[-~-~-~-~-~-~!!{}] // "Infinity"[7] => "y"

    o:([]+{})[+!![]] // "[object Object]", "[object Object]"[1] => "o"

    u:(!![]+[])[-~!![]] // "true"[2] => "u"

    四、== 进行对比的转换

    1. 对象和布尔值,对象先转换为字符串,然后再转换为数字,布尔值直接转换为数字
    [] == true; // false []转换为字符串'',然后转换为数字0,true转换为数字1,所以为false
    2. 对象和字符串,对象转换为字符串,然后两者进行比较。
    [1,2,3] == '1,2,3' // true [1,2,3]转化为'1,2,3',然后和'1,2,3', 结果为true;
    3. 对象和数字,对象先转换为字符串,然后转换为数字,再和数字进行比较。
    [1] == 1; // true `对象先转换为字符串再转换为数字,二者再比较 [1] => '1' => 1 所以结果为true
    4. 字符串和数字,字符串转换成数字,二者再比较。
    '1' == 1 // true
    5. 字符串和布尔值,二者全部转换成数值再比较。
    '1' == true; // true
    6. 布尔值和数字,布尔转换为数字,二者比较。
    true == 1 // true
    7.undefined == null //true undefined和null 比较返回true,二者和其他值比较返回false

    五、运算符的优先级

    参考:

    1.https://segmentfault.com/a/1190000008038678

    2.https://segmentfault.com/a/1190000008572281

    3.https://www.cnblogs.com/chenmeng0818/p/5954215.html

    4.https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Operator_Precedence

  • 相关阅读:
    Web测试与App测试的区别
    unittest参数化
    算法-python
    冒泡排序算法-python
    mysql基础知识
    Web自动化-浏览器驱动chromedriver安装方法
    Selenium-三种等待方式
    C++中进制转换问题
    C++11新特性,对象移动,右值引用,移动构造函数
    C++ 拷贝控制和资源管理,智能指针的简单实现
  • 原文地址:https://www.cnblogs.com/bear-blogs/p/10294257.html
Copyright © 2020-2023  润新知