由于公众号文章的推送规则已经改成了不按照发布时间排序,所以为了大家能够准时收到我们的文章推送,请记得猛戳右下角的
「在看」
,
并点击公号主页右上角的“
...
”将
程序员极客实验室
设为星标~这样就不会错过每一篇精彩的推送啦~
一个阳光明媚的周末,透光的窗帘把我从睡梦中叫醒,大脑说今天是周六,可以慵懒个一上午,于是开心地打开我的 Mac 准备看两集
Rick and Morty
再起床洗漱。
我迫不及待打开了对应的网站,发现浏览器提示 No internet,这才发现因为我的动作太过于行云流水,电脑还没来得及连上 wifi
Fine,那就等 wifi 自己重连吧,等待的这段时间刚好回味一下 Chrome 自带的这款小恐龙游戏。
科普:Chrome 浏览器是 Google 家的官方浏览器,使用体验全世界南波万。当用户在无网络时访问某一网址,浏览器会提示“无网络链接”(也就是上面这张图),按下空格键,就会唤醒一个小恐龙跑步刷分的游戏。
如果在有网络连接时也想玩的话,可以直接在地址栏输入:
chrome://dino
出于职业本身的敏感和好奇,我突然心生疑问:
这应该是用 JS 做的吧?
239
个...太多了,我可没这个耐心
-
-
为什么要看全局变量?
因为假设关于游戏的对象被暴露在了全局
-
如果没暴露在全局?
行,那我就放弃了(周末的早晨我可不想在 sources 里面扒源码)
也就是说,如果没有在全局变量里找到那个对象,我就可以选择性放弃了。
再看一下上面这张图,不难发现,这
239
个全局变量,有很多都是老朋友了,name、history、location、onclick、onerror... 这些变量明显和这只小恐龙没啥关系,打印出来纯粹是来充个数,还浪费了我找目标的时间,所以我遇到了第一个问题:
如何快速找到由开发者自定义的全局变量?
假如我有一个正常的 window...不对,不用假如,新开一个空窗口不就得了
在新打开窗口的控制台,我得到了这样的结果:
也就是说,在这个恐龙快跑的小游戏里,
Google 的前端工程师向 window 注入了 43 个全局变量
(239-196)...
怎么把这
196
个原生的全局变量拿过来呢?复制粘贴就太 low 了,让我想想...
在原有窗口的基础上,再搞一个新窗口...这不就是 iframe 吗!iframe 虽然没有
window
,但是它有
contentWindow
,原则上来说,属性差别应该不大。所以现在只需要创建一个 iframe,拿它里面
contentWindow
的全局变量去过滤当前
window
的全局变量,就可以筛选出那多余的
43
个嫌疑人了。
诶,怎么是
45
个?比预期的多了
2
个,难道
window
里面还包含哪些
contentWindow
里面没有的变量吗?于是我把相同的代码拿去 url 为
about:blank
的窗口下执行了一遍,发现了罪魁祸首:
哦...原来是我给 Chrome 安装的 React 开发者工具干的好事...忽略!
我打开了先前检索到的
45
(43+2) 个多余全局变量,大致扫了一眼,很快就发现了一个很可疑的选手:
Runner
,不就是这个一直在跑步的小恐龙吗
emmm居然是函数,哦?函数,首字母还大写,这熟悉的味道,这不就是个构造函数吗!正所谓,构造函数的宝藏都在
prototype
里,在观察了一遍这个宝藏之后,我发现了一个名为
gameOver
的方法,
这个函数名,难不成它就是那个
让小恐龙去死的方法
?既然这样,呵,我反手就把它
用空函数覆盖
了。于是...
顾名思义,这是用来
给小恐龙设置奔跑速度
的方法,但是怎么调用呢?
由构造函数创建的实例对象,可通过原型链访问构造函数 prototype 上的变量和方法
,也就是说,如果能找到这个小恐龙对应的实例,那么就能直接调用这个
setSpeed
方法了。既然 Google 的前端工程师已经把这么多变量搞到全局了,那么...会不会也在全局存储了这个小恐龙实例?我重新审视了一遍那 43 个多出来的全局变量,并没有找到。我下意识地随手输入了一下这个