当前位置: 首页 > news >正文

浏览器事件循环与内存管理可视化

在这里插入图片描述


<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>浏览器事件循环、内存管理与渲染模拟 - 优化布局版</title><style>* {margin: 0;padding: 0;box-sizing: border-box;font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;}body {background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);color: #fff;min-height: 100vh;padding: 20px;}.container {max-width: 1800px;margin: 0 auto;}header {text-align: center;padding: 20px 0;margin-bottom: 20px;}h1 {font-size: 2.2rem;margin-bottom: 10px;text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);}.subtitle {font-size: 1.1rem;opacity: 0.9;max-width: 800px;margin: 0 auto;line-height: 1.6;}.main-layout {display: grid;grid-template-columns: 1fr 1fr;gap: 20px;margin-bottom: 20px;}.panel {background: rgba(255, 255, 255, 0.1);backdrop-filter: blur(10px);border-radius: 15px;padding: 20px;box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);border: 1px solid rgba(255, 255, 255, 0.2);}.panel h2 {margin-bottom: 15px;padding-bottom: 10px;border-bottom: 1px solid rgba(255, 255, 255, 0.3);display: flex;align-items: center;}.panel h2 .icon {margin-right: 10px;font-size: 1.4rem;}.controls {display: flex;flex-wrap: wrap;gap: 10px;margin-bottom: 20px;}button {background: rgba(255, 255, 255, 0.2);border: none;color: white;padding: 10px 15px;border-radius: 8px;cursor: pointer;transition: all 0.3s ease;font-weight: 500;display: flex;align-items: center;gap: 8px;}button:hover {background: rgba(255, 255, 255, 0.3);transform: translateY(-2px);}button:active {transform: translateY(0);}.speed-controls {display: flex;align-items: center;gap: 10px;margin-top: 15px;}.speed-controls label {font-weight: 500;}.speed-controls input {width: 150px;}.code-editor {background: rgba(0, 0, 0, 0.4);padding: 20px;border-radius: 10px;margin-bottom: 20px;height: 100%;display: flex;flex-direction: column;}.code-input {width: 100%;flex: 1;background: rgba(0, 0, 0, 0.5);color: white;border: 1px solid rgba(255, 255, 255, 0.2);border-radius: 5px;padding: 15px;font-family: 'Courier New', monospace;resize: none;margin-bottom: 15px;font-size: 1rem;line-height: 1.5;}.code-controls {display: flex;gap: 10px;}.memory-queues-container {display: grid;grid-template-rows: 1fr 1fr;gap: 20px;height: 100%;}.memory-container {display: grid;grid-template-columns: 1fr 1fr;gap: 20px;}.memory-panel {background: rgba(0, 0, 0, 0.3);border-radius: 10px;padding: 15px;}.memory-panel h3 {margin-bottom: 10px;display: flex;align-items: center;justify-content: space-between;}.stack {display: flex;flex-direction: column-reverse;gap: 5px;min-height: 150px;}.stack-frame {background: rgba(255, 255, 255, 0.15);padding: 10px;border-radius: 8px;border-left: 4px solid #4CAF50;}.stack-frame.active {background: rgba(76, 175, 80, 0.3);box-shadow: 0 0 10px rgba(76, 175, 80, 0.5);}.heap {display: grid;grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));gap: 10px;min-height: 150px;}.heap-object {background: rgba(255, 255, 255, 0.15);padding: 10px;border-radius: 8px;border-left: 4px solid #2196F3;text-align: center;position: relative;overflow: hidden;}.heap-object.referenced::after {content: '';position: absolute;top: 0;right: 0;width: 10px;height: 10px;background: #FF9800;border-radius: 50%;}.heap-object.garbage {opacity: 0.5;background: rgba(255, 0, 0, 0.2);}.queues-container {display: grid;grid-template-columns: 1fr 1fr 1fr;gap: 20px;}.queue {background: rgba(0, 0, 0, 0.3);border-radius: 10px;padding: 15px;}.queue h3 {margin-bottom: 10px;display: flex;align-items: center;justify-content: space-between;}.task {background: rgba(255, 255, 255, 0.15);padding: 10px;border-radius: 8px;margin-bottom: 8px;display: flex;align-items: center;transition: all 0.3s ease;position: relative;overflow: hidden;}.task.micro {border-left: 4px solid #4CAF50;}.task.macro {border-left: 4px solid #2196F3;}.task.animation {border-left: 4px solid #FF9800;}.task.executing {background: rgba(255, 255, 255, 0.3);transform: scale(1.02);box-shadow: 0 0 10px rgba(255, 255, 255, 0.5);}.task.completed {opacity: 0.7;transform: scale(0.98);}.task-icon {margin-right: 10px;font-size: 1.2rem;}.task-progress {position: absolute;bottom: 0;left: 0;height: 3px;background: rgba(255, 255, 255, 0.7);width: 0%;transition: width 0.1s linear;}.render-container {display: grid;grid-template-columns: 1fr 1fr;gap: 20px;margin-bottom: 20px;}.render-area {height: 200px;background: rgba(0, 0, 0, 0.3);border-radius: 10px;display: flex;align-items: center;justify-content: center;position: relative;overflow: hidden;}.render-box {width: 100px;height: 100px;background: linear-gradient(45deg, #ff0080, #00ff80);border-radius: 10px;transition: all 0.5s ease;display: flex;align-items: center;justify-content: center;color: white;font-weight: bold;text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);}.render-box.rendering {animation: renderAnimation 0.8s ease;}@keyframes renderAnimation {0% { transform: scale(0.8) rotate(0deg); opacity: 0.5; }50% { transform: scale(1.1) rotate(180deg); opacity: 1; }100% { transform: scale(1) rotate(360deg); opacity: 1; }}.event-loop {display: flex;justify-content: center;align-items: center;position: relative;}.loop-circle {width: 300px;height: 300px;border: 3px dashed rgba(255, 255, 255, 0.5);border-radius: 50%;display: flex;align-items: center;justify-content: center;position: relative;animation: rotate 20s linear infinite;}.loop-step {position: absolute;width: 80px;height: 80px;background: rgba(255, 255, 255, 0.1);border-radius: 50%;display: flex;align-items: center;justify-content: center;flex-direction: column;text-align: center;padding: 10px;transition: all 0.3s ease;}.loop-step.active {background: rgba(255, 255, 255, 0.3);box-shadow: 0 0 15px rgba(255, 255, 255, 0.5);}.loop-step-1 {top: -40px;left: 50%;transform: translateX(-50%);}.loop-step-2 {bottom: -40px;left: 50%;transform: translateX(-50%);}.loop-step-3 {left: -40px;top: 50%;transform: translateY(-50%);}.loop-step-4 {right: -40px;top: 50%;transform: translateY(-50%);}@keyframes rotate {from { transform: rotate(0deg); }to { transform: rotate(360deg); }}.output-container {display: grid;grid-template-columns: 1fr 1fr;gap: 20px;}.output-panel {background: rgba(0, 0, 0, 0.3);border-radius: 10px;padding: 15px;height: 300px;display: flex;flex-direction: column;}.output-panel h3 {margin-bottom: 10px;display: flex;align-items: center;justify-content: space-between;}.console-output {background: rgba(0, 0, 0, 0.5);border-radius: 5px;padding: 10px;flex: 1;overflow-y: auto;font-family: 'Courier New', monospace;font-size: 0.9rem;line-height: 1.5;}.console-line {margin-bottom: 5px;}.console-line.log {color: #fff;}.console-line.error {color: #ff6b6b;}.console-line.warn {color: #ffd93d;}.log-container {max-height: 300px;overflow-y: auto;background: rgba(0, 0, 0, 0.3);border-radius: 10px;padding: 15px;}.log-entry {padding: 8px 0;border-bottom: 1px solid rgba(255, 255, 255, 0.1);display: flex;align-items: center;}.log-time {color: #FFD700;margin-right: 10px;font-family: 'Courier New', monospace;}.log-message.micro {color: #4CAF50;}.log-message.macro {color: #2196F3;}.log-message.animation {color: #FF9800;}.log-message.render {color: #E91E63;}.log-message.memory {color: #9C27B0;}.stats {display: grid;grid-template-columns: repeat(4, 1fr);gap: 15px;margin-top: 20px;}.stat-card {background: rgba(255, 255, 255, 0.1);padding: 15px;border-radius: 10px;text-align: center;}.stat-value {font-size: 1.8rem;font-weight: bold;margin: 5px 0;}.stat-label {font-size: 0.8rem;opacity: 0.8;}@media (max-width: 1400px) {.main-layout {grid-template-columns: 1fr;}.memory-queues-container {grid-template-rows: auto;}.queues-container {grid-template-columns: 1fr;}.memory-container {grid-template-columns: 1fr;}.render-container {grid-template-columns: 1fr;}.output-container {grid-template-columns: 1fr;}.stats {grid-template-columns: repeat(2, 1fr);}}@media (max-width: 768px) {.controls {flex-direction: column;}.stats {grid-template-columns: 1fr;}}</style>
</head>
<body><div class="container"><!-- 标题 --><header><h1>浏览器事件循环、内存管理与渲染模拟</h1><p class="subtitle">可视化展示浏览器事件循环机制、内存管理(调用栈、堆)和渲染过程的完整执行流程。支持自定义JavaScript代码模拟。</p></header><!-- 控制面板 --><div class="panel"><h2><span class="icon">⚙️</span> 控制面板</h2><div class="controls"><button id="add-microtask"><span></span> 添加微任务</button><button id="add-macrotask"><span></span> 添加宏任务</button><button id="add-animation"><span>🎬</span> 添加动画任务</button><button id="start-execution"><span>▶️</span> 开始执行</button><button id="pause-execution"><span>⏸️</span> 暂停执行</button><button id="reset-all"><span>🔄</span> 重置模拟</button></div><div class="speed-controls"><label for="execution-speed">执行速度:</label><input type="range" id="execution-speed" min="1" max="10" value="5"><span id="speed-value">中等</span></div><div class="stats"><div class="stat-card"><div class="stat-label">已执行任务</div><div class="stat-value" id="executed-tasks">0</div></div><div class="stat-card"><div class="stat-label">队列中任务</div><div class="stat-value" id="queued-tasks">3</div></div><div class="stat-card"><div class="stat-label">渲染次数</div><div class="stat-value" id="render-count">0</div></div><div class="stat-card"><div class="stat-label">堆对象数</div><div class="stat-value" id="heap-objects">0</div></div></div></div><!-- 主内容区域 --><div class="main-layout"><!-- 左侧:代码编辑器 --><div class="panel"><h2><span class="icon">💻</span> 自定义代码模拟</h2><div class="code-editor"><textarea class="code-input" id="code-input" placeholder="粘贴或输入JavaScript代码...">// 示例代码
console.log('脚本开始');setTimeout(() => {console.log('setTimeout回调');
}, 0);Promise.resolve().then(() => {console.log('Promise.then回调');
});requestAnimationFrame(() => {console.log('requestAnimationFrame回调');
});let user = { name: '张三', age: 30 };
let data = [1, 2, 3, 4, 5];console.log('脚本结束');</textarea><div class="code-controls"><button id="parse-code"><span>🔍</span> 解析代码</button><button id="load-example"><span>📋</span> 加载示例</button></div></div></div><!-- 右侧:内存管理和任务队列 --><div class="memory-queues-container"><!-- 内存管理 --><div class="panel"><h2><span class="icon">🧠</span> 内存管理</h2><div class="memory-container"><div class="memory-panel"><h3>调用栈 (Call Stack) <span id="stack-size">1</span></h3><div class="stack" id="call-stack"><div class="stack-frame active"><strong>全局执行上下文</strong><div>变量: 全局变量</div></div></div></div><div class="memory-panel"><h3>堆 (Heap) <span id="heap-size">0</span></h3><div class="heap" id="heap-memory"></div></div></div></div><!-- 任务队列 --><div class="panel"><h2><span class="icon">📊</span> 任务队列</h2><div class="queues-container"><div class="queue"><h3>宏任务队列 <span id="macro-count">1</span></h3><div id="macro-queue"><div class="task macro"><span class="task-icon"></span><span>初始脚本执行</span><div class="task-progress"></div></div></div></div><div class="queue"><h3>微任务队列 <span id="micro-count">0</span></h3><div id="micro-queue"></div></div><div class="queue"><h3>动画帧队列 <span id="animation-count">0</span></h3><div id="animation-queue"></div></div></div></div></div></div><!-- 渲染模拟 --><div class="render-container"><div class="panel"><h2><span class="icon">🖥️</span> 渲染模拟</h2><div class="render-area"><div class="render-box" id="render-box">渲染区域</div></div></div><div class="panel"><h2><span class="icon">🔄</span> 事件循环</h2><div class="event-loop"><div class="loop-circle"><div class="loop-step loop-step-1" id="loop-step-1"><strong>执行宏任务</strong></div><div class="loop-step loop-step-2" id="loop-step-2"><strong>执行微任务</strong></div><div class="loop-step loop-step-3" id="loop-step-3"><strong>执行动画回调</strong></div><div class="loop-step loop-step-4" id="loop-step-4"><strong>渲染页面</strong></div></div></div></div></div><!-- 输出区域 --><div class="output-container"><div class="panel"><h2><span class="icon">📝</span> 执行日志</h2><div class="log-container" id="log-container"><div class="log-entry"><span class="log-time">00:00:00</span><span class="log-message">模拟器已初始化,准备执行任务</span></div></div></div><div class="panel"><h2><span class="icon">📄</span> 控制台输出</h2><div class="output-panel"><div class="console-output" id="console-output"><div class="console-line log">控制台输出区域...</div></div></div></div></div></div><script>// 任务队列const macroQueue = document.getElementById('macro-queue');const microQueue = document.getElementById('micro-queue');const animationQueue = document.getElementById('animation-queue');const renderBox = document.getElementById('render-box');// 内存管理const callStack = document.getElementById('call-stack');const heapMemory = document.getElementById('heap-memory');// 计数显示const macroCount = document.getElementById('macro-count');const microCount = document.getElementById('micro-count');const animationCount = document.getElementById('animation-count');const stackSize = document.getElementById('stack-size');const heapSize = document.getElementById('heap-size');const executedTasks = document.getElementById('executed-tasks');const queuedTasks = document.getElementById('queued-tasks');const renderCount = document.getElementById('render-count');const heapObjects = document.getElementById('heap-objects');// 事件循环步骤const loopStep1 = document.getElementById('loop-step-1');const loopStep2 = document.getElementById('loop-step-2');const loopStep3 = document.getElementById('loop-step-3');const loopStep4 = document.getElementById('loop-step-4');// 日志容器const logContainer = document.getElementById('log-container');// 控制台输出const consoleOutput = document.getElementById('console-output');// 代码输入const codeInput = document.getElementById('code-input');// 控制变量let taskId = 1;let executedCount = 0;let renderCountValue = 0;let executionSpeed = 5;let isExecuting = false;let currentTask = null;let progressInterval = null;let heapId = 1;let stackFrames = [];let heapObjectsList = [];// 速度映射const speedMap = {1: { name: "非常慢", delay: 2000 },2: { name: "很慢", delay: 1500 },3: { name: "慢", delay: 1000 },4: { name: "较慢", delay: 800 },5: { name: "中等", delay: 600 },6: { name: "较快", delay: 400 },7: { name: "快", delay: 300 },8: { name: "很快", delay: 200 },9: { name: "非常快", delay: 100 },10: { name: "极速", delay: 50 }};// 添加任务函数document.getElementById('add-microtask').addEventListener('click', () => {addTask('micro', `微任务 ${taskId++}`, 'Promise.then()');});document.getElementById('add-macrotask').addEventListener('click', () => {addTask('macro', `宏任务 ${taskId++}`, 'setTimeout()');});document.getElementById('add-animation').addEventListener('click', () => {addTask('animation', `动画任务 ${taskId++}`, 'requestAnimationFrame()');});document.getElementById('start-execution').addEventListener('click', () => {if (!isExecuting) {isExecuting = true;executeEventLoop();}});document.getElementById('pause-execution').addEventListener('click', () => {isExecuting = false;if (currentTask) {currentTask.classList.remove('executing');currentTask = null;}if (progressInterval) {clearInterval(progressInterval);progressInterval = null;}resetLoopSteps();addLog('执行已暂停', 'system');});document.getElementById('reset-all').addEventListener('click', () => {resetSimulation();});// 代码解析document.getElementById('parse-code').addEventListener('click', () => {parseAndSimulateCode(codeInput.value);});// 加载示例代码document.getElementById('load-example').addEventListener('click', () => {codeInput.value = `// 示例代码
console.log('脚本开始');setTimeout(() => {console.log('setTimeout回调');
}, 0);Promise.resolve().then(() => {console.log('Promise.then回调');
});requestAnimationFrame(() => {console.log('requestAnimationFrame回调');
});let user = { name: '张三', age: 30 };
let data = [1, 2, 3, 4, 5];console.log('脚本结束');`;});// 速度控制document.getElementById('execution-speed').addEventListener('input', (e) => {executionSpeed = parseInt(e.target.value);document.getElementById('speed-value').textContent = speedMap[executionSpeed].name;});// 解析并模拟代码function parseAndSimulateCode(code) {resetSimulation();// 清空队列,但保留初始宏任务macroQueue.innerHTML = '<div class="task macro"><span class="task-icon">⏰</span><span>初始脚本执行</span><div class="task-progress"></div></div>';microQueue.innerHTML = '';animationQueue.innerHTML = '';// 重置任务IDtaskId = 1;// 添加日志addLog('开始解析自定义代码', 'system');// 清空控制台输出consoleOutput.innerHTML = '<div class="console-line log">解析代码中...</div>';// 简单的代码解析逻辑const lines = code.split('\n');for (let i = 0; i < lines.length; i++) {const line = lines[i].trim();// 跳过空行和注释if (!line || line.startsWith('//')) continue;// 检测setTimeoutif (line.includes('setTimeout')) {addTask('macro', `宏任务 ${taskId++}`, 'setTimeout回调');addLog(`检测到setTimeout: ${line}`, 'macro');addConsoleOutput('log', '检测到setTimeout,已添加到宏任务队列');}// 检测setIntervalif (line.includes('setInterval')) {addTask('macro', `宏任务 ${taskId++}`, 'setInterval回调');addLog(`检测到setInterval: ${line}`, 'macro');addConsoleOutput('log', '检测到setInterval,已添加到宏任务队列');}// 检测Promise.thenif (line.includes('.then(') || line.includes('.catch(') || line.includes('.finally(')) {addTask('micro', `微任务 ${taskId++}`, 'Promise回调');addLog(`检测到Promise回调: ${line}`, 'micro');addConsoleOutput('log', '检测到Promise回调,已添加到微任务队列');}// 检测requestAnimationFrameif (line.includes('requestAnimationFrame')) {addTask('animation', `动画任务 ${taskId++}`, 'requestAnimationFrame回调');addLog(`检测到requestAnimationFrame: ${line}`, 'animation');addConsoleOutput('log', '检测到requestAnimationFrame,已添加到动画任务队列');}// 检测变量声明if (line.includes('let ') || line.includes('const ') || line.includes('var ')) {const varName = extractVariableName(line);if (varName) {// 检测对象或数组if (line.includes('{') || line.includes('[')) {const objectType = line.includes('{') ? 'Object' : 'Array';addHeapObject(objectType, varName, true);addLog(`检测到${objectType}声明: ${varName}`, 'memory');addConsoleOutput('log', `检测到${objectType}声明: ${varName}`);}}}// 检测函数调用if (line.includes('(') && line.includes(')') && !line.includes('function') && !line.includes('=>') && !line.includes('setTimeout') && !line.includes('setInterval') && !line.includes('requestAnimationFrame')) {const funcName = extractFunctionName(line);if (funcName && funcName !== 'console.log') {addLog(`检测到函数调用: ${funcName}`, 'system');addConsoleOutput('log', `检测到函数调用: ${funcName}`);}}// 检测console.logif (line.includes('console.log')) {const message = extractConsoleMessage(line);if (message) {addConsoleOutput('log', message);}}}addLog('代码解析完成', 'system');addConsoleOutput('log', '代码解析完成,准备执行');updateQueueCounts();}// 提取变量名function extractVariableName(line) {const match = line.match(/(let|const|var)\s+(\w+)/);return match ? match[2] : null;}// 提取函数名function extractFunctionName(line) {const match = line.match(/(\w+)\(/);return match ? match[1] : null;}// 提取console.log消息function extractConsoleMessage(line) {const match = line.match(/console\.log\((['"`])(.*?)\1\)/);return match ? match[2] : null;}// 添加任务到队列function addTask(type, name, description) {const taskElement = document.createElement('div');taskElement.className = `task ${type}`;taskElement.innerHTML = `<span class="task-icon">${getTaskIcon(type)}</span><span>${description || name}</span><div class="task-progress"></div>`;switch(type) {case 'macro':macroQueue.appendChild(taskElement);break;case 'micro':microQueue.appendChild(taskElement);break;case 'animation':animationQueue.appendChild(taskElement);break;}updateQueueCounts();addLog(`已添加${getTaskTypeName(type)}: ${description || name}`, type);}// 获取任务图标function getTaskIcon(type) {switch(type) {case 'macro': return '⏰';case 'micro': return '⚡';case 'animation': return '🎬';default: return '📝';}}// 获取任务类型名称function getTaskTypeName(type) {switch(type) {case 'macro': return '宏任务';case 'micro': return '微任务';case 'animation': return '动画任务';default: return '任务';}}// 更新队列计数function updateQueueCounts() {macroCount.textContent = macroQueue.children.length;microCount.textContent = microQueue.children.length;animationCount.textContent = animationQueue.children.length;const totalQueued = macroQueue.children.length + microQueue.children.length + animationQueue.children.length;queuedTasks.textContent = totalQueued;}// 添加控制台输出function addConsoleOutput(type, message) {const now = new Date();const timeString = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`;const outputLine = document.createElement('div');outputLine.className = `console-line ${type}`;outputLine.innerHTML = `<span class="console-time">${timeString}</span> ${message}`;consoleOutput.appendChild(outputLine);consoleOutput.scrollTop = consoleOutput.scrollHeight;}// 添加栈帧function pushStackFrame(name, variables) {const frameId = `frame-${Date.now()}`;const frame = {id: frameId,name: name,variables: variables || []};stackFrames.push(frame);const frameElement = document.createElement('div');frameElement.className = 'stack-frame';frameElement.id = frameId;frameElement.innerHTML = `<strong>${name}</strong><div>变量: ${variables ? variables.join(', ') : '无'}</div>`;// 取消之前活跃的栈帧const activeFrames = callStack.querySelectorAll('.stack-frame.active');activeFrames.forEach(frame => frame.classList.remove('active'));// 添加新栈帧并标记为活跃callStack.appendChild(frameElement);frameElement.classList.add('active');stackSize.textContent = stackFrames.length;return frameId;}// 移除栈帧function popStackFrame(frameId) {const frameIndex = stackFrames.findIndex(frame => frame.id === frameId);if (frameIndex !== -1) {stackFrames.splice(frameIndex, 1);}const frameElement = document.getElementById(frameId);if (frameElement) {frameElement.remove();}// 激活上一个栈帧if (stackFrames.length > 0) {const lastFrameId = stackFrames[stackFrames.length - 1].id;const lastFrameElement = document.getElementById(lastFrameId);if (lastFrameElement) {lastFrameElement.classList.add('active');}}stackSize.textContent = stackFrames.length;}// 添加堆对象function addHeapObject(type, value, referenced = true) {const objectId = `heap-${heapId++}`;const object = {id: objectId,type: type,value: value,referenced: referenced};heapObjectsList.push(object);const objectElement = document.createElement('div');objectElement.className = `heap-object ${referenced ? 'referenced' : 'garbage'}`;objectElement.id = objectId;objectElement.innerHTML = `<div><strong>${type}</strong></div><div>${value}</div>`;heapMemory.appendChild(objectElement);heapSize.textContent = heapObjectsList.length;heapObjects.textContent = heapObjectsList.length;return objectId;}// 标记堆对象为垃圾function markHeapObjectAsGarbage(objectId) {const object = heapObjectsList.find(obj => obj.id === objectId);if (object) {object.referenced = false;const objectElement = document.getElementById(objectId);if (objectElement) {objectElement.classList.remove('referenced');objectElement.classList.add('garbage');}}}// 执行垃圾回收function runGarbageCollection() {const garbageObjects = heapObjectsList.filter(obj => !obj.referenced);garbageObjects.forEach(obj => {const objectElement = document.getElementById(obj.id);if (objectElement) {objectElement.remove();}const objectIndex = heapObjectsList.findIndex(o => o.id === obj.id);if (objectIndex !== -1) {heapObjectsList.splice(objectIndex, 1);}});heapSize.textContent = heapObjectsList.length;heapObjects.textContent = heapObjectsList.length;if (garbageObjects.length > 0) {addLog(`垃圾回收: 释放了 ${garbageObjects.length} 个对象`, 'memory');addConsoleOutput('log', `垃圾回收: 释放了 ${garbageObjects.length} 个对象`);}}// 模拟事件循环async function executeEventLoop() {if (!isExecuting) return;// 执行宏任务if (macroQueue.children.length > 0) {await executeTask('macro', macroQueue);if (!isExecuting) return;}// 执行微任务while (microQueue.children.length > 0 && isExecuting) {await executeTask('micro', microQueue);if (!isExecuting) return;}// 执行动画任务if (animationQueue.children.length > 0 && isExecuting) {await executeTask('animation', animationQueue);if (!isExecuting) return;}// 渲染if (isExecuting) {await executeRender();}// 垃圾回收if (Math.random() > 0.7) { // 随机触发垃圾回收runGarbageCollection();}// 如果还有任务,继续执行if ((macroQueue.children.length > 0 || microQueue.children.length > 0 || animationQueue.children.length > 0) && isExecuting) {setTimeout(executeEventLoop, 100);} else {isExecuting = false;addLog('所有任务执行完成', 'system');addConsoleOutput('log', '所有任务执行完成');}}// 执行单个任务async function executeTask(type, queue) {const task = queue.children[0];if (!task) return;currentTask = task;task.classList.add('executing');// 高亮对应的事件循环步骤highlightLoopStep(type);// 添加执行日志const taskDescription = task.textContent.trim();addLog(`开始执行: ${taskDescription}`, type);addConsoleOutput('log', `开始执行: ${taskDescription}`);// 模拟函数调用 - 添加栈帧const frameId = pushStackFrame(taskDescription,['局部变量1', '局部变量2']);// 模拟堆分配 - 随机创建一些对象if (Math.random() > 0.5) {const objectTypes = ['Object', 'Array', 'Function', 'String'];const objectType = objectTypes[Math.floor(Math.random() * objectTypes.length)];const objectValue = generateRandomValue(objectType);addHeapObject(objectType, objectValue, true);addLog(`堆分配: 创建了 ${objectType} 对象`, 'memory');addConsoleOutput('log', `堆分配: 创建了 ${objectType} 对象`);}// 开始进度条动画const progressBar = task.querySelector('.task-progress');let progress = 0;progressInterval = setInterval(() => {progress += 2;progressBar.style.width = `${progress}%`;if (progress >= 100) {clearInterval(progressInterval);progressInterval = null;}}, speedMap[executionSpeed].delay / 50);// 等待任务执行完成await delay(speedMap[executionSpeed].delay);if (progressInterval) {clearInterval(progressInterval);progressInterval = null;}// 模拟函数返回 - 移除栈帧popStackFrame(frameId);// 随机标记一些对象为垃圾if (heapObjectsList.length > 0 && Math.random() > 0.7) {const randomIndex = Math.floor(Math.random() * heapObjectsList.length);const randomObject = heapObjectsList[randomIndex];if (randomObject && randomObject.referenced) {markHeapObjectAsGarbage(randomObject.id);addLog(`对象 ${randomObject.type} 不再被引用`, 'memory');addConsoleOutput('log', `对象 ${randomObject.type} 不再被引用`);}}task.classList.remove('executing');task.classList.add('completed');// 短暂显示完成状态后移除await delay(300);task.remove();// 更新计数executedCount++;executedTasks.textContent = executedCount;updateQueueCounts();currentTask = null;addLog(`完成执行: ${taskDescription}`, type);addConsoleOutput('log', `完成执行: ${taskDescription}`);}// 执行渲染async function executeRender() {highlightLoopStep('render');addLog('开始页面渲染', 'render');addConsoleOutput('log', '开始页面渲染');renderBox.classList.add('rendering');renderCountValue++;renderCount.textContent = renderCountValue;await delay(speedMap[executionSpeed].delay);renderBox.classList.remove('rendering');addLog('页面渲染完成', 'render');addConsoleOutput('log', '页面渲染完成');}// 高亮事件循环步骤function highlightLoopStep(type) {resetLoopSteps();switch(type) {case 'macro':loopStep1.classList.add('active');break;case 'micro':loopStep2.classList.add('active');break;case 'animation':loopStep3.classList.add('active');break;case 'render':loopStep4.classList.add('active');break;}}// 重置事件循环步骤高亮function resetLoopSteps() {loopStep1.classList.remove('active');loopStep2.classList.remove('active');loopStep3.classList.remove('active');loopStep4.classList.remove('active');}// 生成随机值function generateRandomValue(type) {switch(type) {case 'Object':return `{key: "value${Math.floor(Math.random() * 100)}"}`;case 'Array':return `[${Math.floor(Math.random() * 10)}, ${Math.floor(Math.random() * 10)}]`;case 'Function':return `function${Math.floor(Math.random() * 10)}()`;case 'String':return `"string${Math.floor(Math.random() * 100)}"`;default:return "unknown";}}// 重置模拟function resetSimulation() {isExecuting = false;if (currentTask) {currentTask.classList.remove('executing');currentTask = null;}if (progressInterval) {clearInterval(progressInterval);progressInterval = null;}// 清空队列macroQueue.innerHTML = '<div class="task macro"><span class="task-icon">⏰</span><span>初始脚本执行</span><div class="task-progress"></div></div>';microQueue.innerHTML = '';animationQueue.innerHTML = '';// 清空内存callStack.innerHTML = '<div class="stack-frame active"><strong>全局执行上下文</strong><div>变量: 全局变量</div></div>';heapMemory.innerHTML = '';// 重置内存数据stackFrames = [];heapObjectsList = [];heapId = 1;// 重置计数taskId = 1;executedCount = 0;renderCountValue = 0;executedTasks.textContent = '0';renderCount.textContent = '0';stackSize.textContent = '1';heapSize.textContent = '0';heapObjects.textContent = '0';// 更新队列计数updateQueueCounts();// 重置事件循环步骤resetLoopSteps();// 清空日志logContainer.innerHTML = '';addLog('模拟器已重置', 'system');// 清空控制台输出consoleOutput.innerHTML = '<div class="console-line log">模拟器已重置</div>';}// 添加日志function addLog(message, type) {const now = new Date();const timeString = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`;const logEntry = document.createElement('div');logEntry.className = 'log-entry';logEntry.innerHTML = `<span class="log-time">${timeString}</span><span class="log-message ${type}">${message}</span>`;logContainer.appendChild(logEntry);logContainer.scrollTop = logContainer.scrollHeight;}// 延迟函数function delay(ms) {return new Promise(resolve => setTimeout(resolve, ms));}// 初始化示例任务function initializeExampleTasks() {addTask('micro', '微任务 1', 'Promise.then()');addTask('macro', '宏任务 1', 'setTimeout()');addTask('animation', '动画任务 1', 'requestAnimationFrame()');addTask('micro', '微任务 2', 'Promise.resolve().then()');addTask('macro', '宏任务 2', 'setInterval()');// 初始化一些堆对象addHeapObject('Object', '{name: "user", age: 30}');addHeapObject('Array', '[1, 2, 3, 4, 5]');addHeapObject('Function', 'function clickHandler()');}// 页面加载后初始化window.addEventListener('load', () => {initializeExampleTasks();addLog('模拟器已初始化,准备执行任务', 'system');addConsoleOutput('log', '模拟器已初始化,准备执行任务');});</script>
</body>
</html>
http://www.dtcms.com/a/457325.html

相关文章:

  • 虚拟机双网卡设置
  • 吴恩达机器学习课程(PyTorch适配)学习笔记:2.2 前向传播与推理
  • 530.二叉搜索树的最小绝对差(二叉树算法题)
  • 如何解决 pip install -r requirements.txt extras 语法 ‘package[extra’ 缺少 ‘]’ 解析失败问题
  • 青岛网站建设方案辽阳网站建设
  • 磁悬浮轴承中基于位移信号的转子位置与转速估计深度解析摘要
  • 个人和做网站方签合同模板一流的聊城网站建设
  • 什么是UIOTOS?
  • 网站建设书籍论文龙网网络推广软件
  • 蚌埠网站制作公司排名wordpress lazyload
  • Windows中通过wsl运行Ubuntu
  • TensorFlow2 Python深度学习 - TensorFlow2框架入门 - 计算图和 tf.function 简介
  • 怎样理解网站建设与开发这门课郑州妇科医院正规有哪些
  • 使用 C 语言连接 MySQL 客户端(重点)
  • 西安网站建设价格明细网站建设项目合同
  • 中国建设银行密码重置网站邯郸模板建站教程
  • HFish架构深度解析:从蜜罐诱捕到威胁狩猎的完整技术链路
  • 最小栈GO实现
  • 福田欧辉是国企吗做百度手机网站优化点
  • npm 扩展vite
  • 和15岁女儿做很舒服网站最新网页版传奇
  • 01.MMDetection3D训练
  • 手机 网站制作什么网站资源多
  • C++之日期类的实现
  • 构建AI智能体:五十七、LangGraph + Gradio:构建可视化AI工作流的趣味指南
  • Create/Assemble/Link x64 Windows
  • 网站建设与管理案例教程第三版答案中国货源大全网
  • 织梦建网站建设收费网站
  • Delphi字段值含有空格
  • 【第五章:计算机视觉-项目实战之生成式算法实战:扩散模型】2.CV黑科技:生成式算法理论-(3)经典扩散模型DDPM算法流程讲解