日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

JavaScript打印所有被执行函数堆栈

發布時間:2024/3/24 javascript 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JavaScript打印所有被执行函数堆栈 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

需求

  • 學習已有項目/框架時, 想要分析代碼所有運行;
  • 開發項目邏輯分析, 排錯.
  • 項目地址

    Github

    效果

    思路

  • 將代碼轉換為抽象語法樹
  • 根據需要對語法樹進行修改
  • 將語法樹轉換為代碼
  • 實現

    const fs = require('fs') const escodegen = require("escodegen"); const esprima = require('esprima');const srcPath = "./demo/three.js"; const destPath = './demo/three_log.js'; /** 是否顯示堆棧信息 */ const isShowStack = false; let prevHandleTime = 0;main(srcPath, destPath);function main(srcPath, destPath) {log('讀取文件');const program = fs.readFileSync(srcPath, "utf-8");log('文本轉AST');let tree = esprima.parseScript(program);log('處理AST');handleTree(tree);log('AST轉文本');const result = escodegen.generate(tree);// console.log(result);log('寫入新文本');fs.writeFileSync(destPath, result);log('Finish'); }function handleTree(tree, methodName = "") {if (!tree) return;if (checkIsObject(tree)) {switch (tree.type) {case 'BlockStatement':if (tree.body && checkIsArray(tree.body)) {let logStr = '';if (isShowStack) {logStr =`console.groupCollapsed("---------------------------------${methodName}"); console.trace("${methodName}");console.groupEnd(); `;} else {logStr = `console.log("---------------------------------${methodName}");`;}const consoleBody = esprima.parseScript(logStr).body;if (tree.body.length > 0) {// 空方法不添加log for (let i = consoleBody.length - 1; i >= 0; i--)tree.body.unshift(consoleBody[i]);}handleTree(tree.body, methodName);return;}break;case 'AssignmentExpression':tree.right && handleTree(tree.right, getName(methodName, tree.left));break;case 'CallExpression':if (tree.callee) {handleTree(tree.callee, methodName);}if (tree.arguments) {handleTree(tree.arguments, methodName);}break;case 'ClassDeclaration':tree.body && handleTree(tree.body, getName(methodName, tree));break;default:tree.body && handleTree(tree.body, methodName);break;}return;}if (checkIsArray(tree)) {for (let i = 0; i < tree.length; i++) {let item = tree[i];switch (item.type) {case 'MethodDefinition':if (item.kind === 'get' || item.kind === 'set') {// 過濾 get/set 方法} else {item.value && handleTree(item.value, getName(methodName, item));}break;case 'ExpressionStatement':item.expression && handleTree(item.expression, methodName);break;case 'ClassDeclaration':item.body && handleTree(item.body, getName(methodName, item));break;case 'ForStatement':case 'ForInStatement':// for 語句不添加break;case 'FunctionDeclaration':// 方法聲明item.body && handleTree(item.body, getName(methodName, item));break;default:item.body && handleTree(item.body, methodName);break;}}return;}console.error('什么鬼'); }function getName(methodName, item) {let itemName = '';if (item) {if (item.id)itemName = item.id.name;else if (item.key)itemName = item.key.name;else if (item.property)itemName = item.property.name;}let dot = '';if (methodName && itemName)dot = '.';return methodName + dot + itemName; }function checkIsArray(arr) {return Object.prototype.toString.call(arr) === '[object Array]'; }function checkIsObject(obj) {return Object.prototype.toString.call(obj) === '[object Object]'; }function getTime() {const now = Date.now();let result = 0;if (prevHandleTime !== 0) {result = now - prevHandleTime;}prevHandleTime = now;return ' ' + result + ' ms'; }function log(str) {console.log(str, getTime()); }

    拓展

    靈活使用, 可大幅提高分析效率, 如:

  • 字符串排除打印;
  • 重復不打印;
  • 指定時間打印;
  • 總結

    以上是生活随笔為你收集整理的JavaScript打印所有被执行函数堆栈的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。