记一次pvuv与vConsole在IE上的打架

背景

这周在开发一个答题测评需求,只有一个页面,很开心地写完了,然后一顿自测,各种浏览器安卓端IOS端,然后IE又没有让人失望地报错了,整个页面出不来。先看下这个小婊砸:

pwd

看了下报错,这个ua-parser.js是什么,点进去再打个断点调试下,发现是将一个函数当成字符串去调用toLowerCase方法。函数是没有toLowerCase方法呀,难道冤枉IE了。

pwd

根因

看下调用堆栈,这个str1看样子应该是个字符串,怎么会出来一个函数咧,然后发现调用的地方是用for in来循环的,这个入参是个字符串数组,没毛病,但是此时的j很奇怪,值是__symbol_iterator_key,按道理应该只是0或者1,不过因为是for in留了个心眼,考虑是不是原型上的属性,把map[i]再点开来,果然看到一个叫这个名字的家伙。

pwd
pwd

元凶找到了,再就是找下这个是怎么来的,为什么亲爱的谷歌没有呢?

排查

不死心还是要怀疑IE,难道IE上的数组原型自带的?还可以被枚举出来?在控制台打了下Array.prototype看下,发现是自己想太多,回到谷歌同样的地方打断点看下,发现并没有__symbol_iterator_key这个属性,所以谷歌没有问题。

回到ua-parser.js,发现这个是页面上报组件tool-pvuv中引用的用于判断当前浏览器、操作系统、设备的库user-agent-parsertool-pvuv中当前用的是0.6.0版本的。再看下调式过程中看到的这个数组的来历,发现就是简简单单写的一个数组常量,太没毛病了。

pwd

数据来源没问题,那就是页面其他js给数组原型加了__symbol_iterator_key这个属性,导致后面创建的数组都带有这个东西。看了下页面引用的库,嗯。。有点多,有的还是复制其他页面引用的公共库,不知道干啥的,咳咳,尴尬,确实给自己埋下了不少坑,填坑路漫漫~~

不过既然是页面加载的时候加上去的,全局搜下应该可以搜到吧,简单粗暴在整个工程中搜了一把__symbol_iterator_key,还真的找到了,看来这个才是元凶!!!

pwd

看了下是公共代码commonMain.js中打包了vConsole的代码,一坨压缩后的实在难看,然后又跑来IE上调试,==,还是谷歌吧,顺便吐槽IE这个调试,期间各种不响应问我要不要重启。。。回到正题,看下图所有疑问都有了答案,感觉一阵神清气爽,正是判断了这个Symbol有没有定义,导至出现谷歌与IE的区别,IE没有Symbol的实现,所以IE上面的数组原型就有了那个函数,看样子应该是提供了数组的Iterator 接口。

pwd

谁的锅

看问题导致的原因是vConsole里面的一段代码提供了在IE上的数组Iterator接口,所以才会出现IE上的报错,但是这个问题最应该改的应该还是ua-parser.js里面写的那个for in,而且for in中还没有判断是否是自有属性,这样一不小心就不知道遍历到哪里去了,上github上看了下最新的代码,果然已经修改成了最原始可靠的for循环,这样只需要更新下pvuv中引用的user-agent-parser就可以啦,已经知会pvuv的维护童鞋~~~