Quảng cáo

Viết và chạy JavaScript ngay lập tức trong môi trường sandbox an toàn — xem kết quả console, giá trị trả về, lỗi và thời gian mà không cần mở DevTools. Miễn phí và chạy ngay trong trình duyệt của bạn.

Chạy trong một iframe sandbox trong trình duyệt của bạn — không có gì được gửi đến máy chủ.

Nhấn Ctrl/⌘ + Enter để chạy
JavaScript
1
Console
>_ Kết quả console xuất hiện ở đây

Cần trợ giúp?
Gặp sự cố với công cụ này? Hãy cho đội ngũ của chúng tôi biết.
Báo cáo sự cố

Thêm công cụ miễn phí này vào trang web của riêng bạn — sao chép và dán mã bên dưới.

', ].join('\n'); } function destroyFrame() { if (frame && frame.parentNode) frame.parentNode.removeChild(frame); frame = null; } function run() { const code = input.value; if (code.trim() === '') { clearConsole(); return; } // New token; any message from an older frame is now stale. runToken++; const token = runToken; // Recreate the iframe so prior state resets and runaway code is discarded. destroyFrame(); clearConsole(); ghost.style.display = 'none'; statusEl.dataset.state = 'idle'; statEl.textContent = '…'; frame = document.createElement('iframe'); frame.setAttribute('sandbox', 'allow-scripts'); frame.setAttribute('aria-hidden', 'true'); frame.style.cssText = 'position:absolute;width:0;height:0;border:0;left:-9999px;top:-9999px'; frame.srcdoc = buildSandboxDoc(code, token); document.body.appendChild(frame); } window.addEventListener('message', function (ev) { const d = ev.data; if (!d || d.__jst !== true) return; if (d.token !== runToken) return; // ignore stale frames if (d.kind === 'done') { let info = { ok: true, ms: 0 }; try { info = JSON.parse(d.text); } catch (e) {} statusEl.dataset.state = info.ok ? 'ok' : 'error'; if (info.ok) { statEl.innerHTML = tr(L.finished, { ms: nf.format(info.ms) }); } else { statEl.textContent = L.error; } if (lineCount === 0 && info.ok) ghost.style.display = 'flex'; return; } appendLine(d.kind, d.text); }); /* ---------------- controls ---------------- */ root.querySelector('[data-jst-run]').addEventListener('click', run); root.querySelector('[data-jst-clearlog]').addEventListener('click', clearConsole); root.querySelector('[data-jst-clear]').addEventListener('click', function () { input.value = ''; renderGutter(); input.focus(); }); root.querySelector('[data-jst-sample]').addEventListener('click', function () { input.value = [ "// Try editing and press Run (Ctrl/Cmd+Enter)", "const nums = [5, 2, 9, 1, 7];", "console.log('sorted:', [...nums].sort((a, b) => a - b));", "", "const user = { name: 'Ada', skills: ['math', 'code'], active: true };", "console.info(user);", "", "console.warn('heads up: this is a warning');", "", "async function ping() {", " await new Promise((r) => setTimeout(r, 50));", " return 'pong';", "}", "ping().then((v) => console.log('async →', v));", ].join('\n'); renderGutter(); run(); input.focus(); }); /* ---------------- editor behaviour ---------------- */ let autoTimer = null; input.addEventListener('input', function () { renderGutter(); if (autorunCb.checked) { clearTimeout(autoTimer); autoTimer = setTimeout(run, 600); } }); // Tab inserts a tab instead of moving focus. input.addEventListener('keydown', function (e) { if (e.key === 'Tab') { e.preventDefault(); const s = input.selectionStart, en = input.selectionEnd; input.value = input.value.slice(0, s) + '\t' + input.value.slice(en); input.selectionStart = input.selectionEnd = s + 1; renderGutter(); return; } if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') { e.preventDefault(); run(); } }); autorunCb.addEventListener('change', function () { if (autorunCb.checked) run(); }); renderGutter(); })();