好玩的浏览器检测方法

日常不务正业

Posted by 恋 on February 20, 2019

dalao群讨论到浮点数标准的时候吐槽了一下JavaScript的浮点数精度问题,然后莫名发现了一些有意思的浏览器特点

先吐槽一下,居然有十进制的浮点数…我一直以为只有二进制的

在说到十进制浮点数和二进制浮点数的时候,提到了一个检测的方法:0.1+0.2==0.3… 因为二进制浮点数没办法正确表示这数字,所以总是不等的。这时候突然开始吐槽(黑)了一下js的精度问题,于是就观察了一些东西。

众所周知,2的幂不会是0结尾的… 然而Chrome里面2 ** 63的结果是9223372036854776000(正确应为9223372036854775808)。

但是这个肯定是js独有的坑:Math.pow(99, 99) != 99 ** 99

Math.pow(99, 99) == 99 ** 99
// false
3.697296376497263e+197 == Math.pow(99, 99)
// true
3.697296376497268e+197 == 99 ** 99
// true

(经过实际测试,发现这个问题不存在于Firefox/Edge/IE中:就是说,这是个Chrome独有的bug - 或者说是V8的。IE不存在这个问题是因为不支持ES7,所以没办法用**运算符…IE:今天我是流泪狗狗头

经过进一步的研究(把几种可能暴力组合后)发现,这个问题只出现于硬编码的计算当中(即99 ** 99),其余的方法(例如说var x = 99; x ** x这样都不会出现问题)

于是沙雕群友就在群里发了这样的代码:

try {
    if (Math.pow(99, 99) != 99 ** 99) console.log('Chrome');
    else if (99 ** 99 == 3.697296376497263e+197) console.log('Firefox');
    else if (99 ** 99 == 3.697296376497268e+197) console.log('Edge');
    else console.log('未知浏览器');
} catch (err) {
    console.log('你的浏览器不支持ES7'); // 说的就是你@IE
}

蛇精病的我突然开始好奇 还有什么别的骚操作可以检查浏览器环境吗… 根据经验,UA是个不怎么靠谱的方案,感觉各种被改… 貌似找js的运行时或环境里的神秘坑会有点用

很容易就找到了浏览器里的一个叫navigator的玩意儿… 虽然恕我直言,这里面一大半的玩意儿都会返回固定的(错误的)值。

  Chrome Firefox Edge IE Opera Safari
Math.pow(99, 99) 3.697296376497263e+197 3.697296376497263e+197 3.697296376497268e+197 3.697296376497268e+197 3.697296376497263e+197 不明
99 ** 99 3.697296376497268e+197 3.697296376497263e+197 3.697296376497268e+197 ES7不支持 3.697296376497268e+197 不明
navigator.vendor "Google Inc." "" "" "" 不明 "Apple Computer, Inc."*
navigator.oscpu undefined Windows NT 10.0; Win64; x64 undefined undefined undefined undefined
navigator.platform "Win32" "Win32" "Win32" "Win32" "Win32" "Win32"
navigator.product "Gecko" "Gecko" "Gecko" "Gecko" "Gecko" "Gecko"
navigator.productSub "20030107" "20100101" "20030107" undefined "20030107" "20030107"*
navigator.webdriver undefined truefalse truefalse truefalse 不明 不明
escape(Math.pow.toString()) 一行"function pow() { [native code] }" 三行"function pow() {\r\n [native code]\r\n}" 一行"function pow() { [native code] }" 五行"\r\nfunction pow() {\r\n [native code]\r\n}\r\n" 一行"function pow() { [native code] }" 不明

大致总结:

只有Firefox有navigator.oscpu

Chrome和Safari有navigator.vendor

Chrome的Math.pow(99, 99) != 99 ** 99,Firefox的计算结果以3结尾,Edge的结果以8结尾

方法toString后IE为五行,Firefox三行,其余一行

(这玩意儿有个*用啊…