如何获取对应场景源代码?怎样恢复indexOf功能?
不同运行场景下获取源代码的方式差异很大,我整理了几种常见场景的实用方法:
浏览器控制台获取页面脚本/函数源码
要是想查看某个全局函数或变量的源码,直接在控制台输入函数名(别加括号)回车就行。比如查看myCustomFunc的源码:myCustomFunc // 控制台会直接输出这个函数的完整定义想批量获取页面中所有
<script>标签里的代码?用这段遍历代码就行:Array.from(document.querySelectorAll('script')).forEach(script => { console.log('脚本内容/地址:', script.textContent || script.src); });注意:如果是外部引入的脚本(带
src属性),浏览器出于安全限制可能没法直接拿到源码,这时候去开发者工具的「Sources」(Chrome)或「调试器」(Firefox)面板里找对应的文件就行,一般都能看到。Node.js环境获取模块/函数源码
在Node.js里,读取本地文件源码用内置的fs模块就搞定了,比如读当前目录的utils.js:const fs = require('fs'); fs.readFile('./utils.js', 'utf8', (err, code) => { if (err) throw err; console.log(code); });要是只想看某个函数的源码,直接调用
toString()方法:function calculateSum(a, b) { return a + b; } console.log(calculateSum.toString());框架组件源码(React/Vue等)
现代框架的组件代码大多会被打包压缩,不过只要项目开启了source map,你可以用对应的开发者工具:React找「Components」面板,Vue用「Vue Devtools」,找到目标组件后点击「查看源码」就能跳转到未压缩的源文件。
这种情况一般是Array.prototype.indexOf或者String.prototype.indexOf被第三方脚本不小心重写了,下面是几种靠谱的恢复方案:
从干净iframe中拿原生方法
新建一个iframe,它的全局环境是完全干净的,里面的indexOf是原生未被修改的,把它赋值回当前环境就行:// 恢复Array.prototype.indexOf const cleanIframe = document.createElement('iframe'); document.body.appendChild(cleanIframe); Array.prototype.indexOf = cleanIframe.contentWindow.Array.prototype.indexOf; document.body.removeChild(cleanIframe); // 恢复String.prototype.indexOf同理 String.prototype.indexOf = cleanIframe.contentWindow.String.prototype.indexOf;手动实现符合标准的indexOf
要是没法创建iframe(比如某些受限环境),可以手动按照ECMAScript标准实现indexOf,确保和原生行为完全一致:// 恢复Array.prototype.indexOf if (!Array.prototype.indexOf || !Array.prototype.indexOf.toString().includes('[native code]')) { Array.prototype.indexOf = function(searchElement, fromIndex) { const length = this.length; let start = fromIndex == null ? 0 : Number(fromIndex); start = start < 0 ? Math.max(length + start, 0) : start; for (let i = start; i < length; i++) { if (this[i] === searchElement) return i; } return -1; }; } // 恢复String.prototype.indexOf if (!String.prototype.indexOf || !String.prototype.indexOf.toString().includes('[native code]')) { String.prototype.indexOf = function(searchValue, fromIndex) { const str = this; const searchLength = searchValue.length; const strLength = str.length; let start = fromIndex == null ? 0 : Number(fromIndex); start = start < 0 ? Math.max(strLength + start, 0) : start; if (searchLength === 0) return start; for (let i = start; i <= strLength - searchLength; i++) { if (str.slice(i, i + searchLength) === searchValue) return i; } return -1; }; }这里加了个判断,只有当方法不是原生的时候才覆盖,避免没必要的操作。
尝试从属性描述符恢复
如果重写只是简单赋值,没修改属性的descriptor,还可以用Object.getOwnPropertyDescriptor获取原始定义,但这种方法不一定可靠,要是重写时覆盖了descriptor就没用了:// 恢复Array.prototype.indexOf示例 const originalIndexOf = Object.getOwnPropertyDescriptor(Array.prototype, 'indexOf').value; Array.prototype.indexOf = originalIndexOf;
内容的提问来源于stack exchange,提问作者Ruby Jacob

