[{"data":1,"prerenderedAt":1736},["ShallowReactive",2],{"search-dialog-posts":3,"post-\u002Fposts\u002Fstructured-clone":316,"post-surround-\u002Fposts\u002Fstructured-clone":1729},[4,12,21,29,37,47,57,67,77,85,96,104,112,121,129,137,147,155,164,173,181,188,195,207,215,224,236,241,247,254,260,266,272,279,286,291,298,304,310],{"path":5,"title":6,"description":7,"category":8,"tags":9},"\u002Fposts\u002Fgit-commands-cheatsheet","Git 常用指令與終端機筆記","2018 年整理的 Git 學習筆記，包含基本終端機指令、Git 操作、分支、reset、SourceTree、Vim 與一些常用設定。","notes",[10,11],"Git","版本控制",{"path":13,"title":14,"description":15,"category":16,"tags":17},"\u002Fposts\u002Fjs-prototype-inheritance","JavaScript 物件導向：建構函式、prototype 與繼承三步驟","整理 ES5 時代用建構函式加 prototype 手刻物件導向的完整流程——封裝屬性與方法、共用函式為什麼要掛在 prototype 上、以及繼承的三個步驟（call 借用母類別建構子、Object.create 接上原型鏈、修正 constructor 指向），並附上物件縮寫與計算屬性這兩個順便學到的 ES6 寫法。","frontend",[18,19,20],"JavaScript","物件導向","prototype",{"path":22,"title":23,"description":24,"category":16,"tags":25},"\u002Fposts\u002Fflexbox-notes","Flexbox 對齊與彈性尺寸筆記","記錄 Flexbox 的主軸與交錯軸對齊、flex-direction、flex-wrap，以及 flex-grow、flex-shrink、flex-basis 等常用屬性。",[26,27,28],"CSS","Flexbox","版面",{"path":30,"title":31,"description":32,"category":16,"tags":33},"\u002Fposts\u002Fscreen-orientation-api","screen.orientation：現在判斷與鎖定螢幕方向的做法","整理現在 JavaScript 判斷螢幕方向的方式，包括 screen.orientation、change 事件與 lock()，並說明 RWD 使用 matchMedia 或 CSS orientation 會更適合。",[18,34,35,36],"RWD","螢幕方向","PWA",{"path":38,"title":39,"description":40,"category":16,"tags":41},"\u002Fposts\u002Fpinia-vuex-state-management","Pinia \u002F Vuex 狀態管理及差異","紀錄 Vuex、Pinia 的狀態管理概念、差異與用法。",[42,43,44,45,46],"Pinia","Vuex","Vue3","狀態管理","Nuxt",{"path":48,"title":49,"description":50,"category":8,"tags":51},"\u002Fposts\u002Fpyenv-python-version-management","Python 多版本管理 pyenv","紀錄 macOS 與 Windows 使用 pyenv 管理 Python 版本的方式。",[52,53,54,55,56],"Python","pyenv","macOS","Windows","版本管理",{"path":58,"title":59,"description":60,"category":8,"tags":61},"\u002Fposts\u002Fnpm-publish-vue2-component","npm 發布流程","紀錄 Vue 2 元件的 npm 發布、dist-tag 與打包流程。",[62,63,64,65,66],"npm","Vue2","Vue CLI","套件發布","MIT",{"path":68,"title":69,"description":70,"category":8,"tags":71},"\u002Fposts\u002Fmobile-debugging-today","現在怎麼 debug 手機網頁：從裝一堆工具到幾乎不用裝","對照 2022 年那套 scoop、iTunes、remotedebug-ios-webkit-adapter 的繁瑣設定，整理現在偵錯手機網頁的做法：Android 無線偵錯、iOS 的實際選項、on-device console、Playwright 裝置模擬，以及本機 HTTPS 的處理。",[72,73,74,75,76],"debug","iOS","Android","Chrome DevTools","Playwright",{"path":78,"title":79,"description":80,"category":16,"tags":81},"\u002Fposts\u002Fplaywright-vs-cypress","E2E 測試現在選什麼：Playwright 與 Cypress 的實際差異","對照幾年前用 Cypress 的做法，說明 Playwright 為什麼變成多數新專案的預設選擇：真正的多瀏覽器支援、免費的平行執行、trace viewer 除錯，以及兩者在架構上的根本差異與各自仍然適合的場景。",[76,82,83,84],"Cypress","E2E","測試",{"path":86,"title":87,"description":88,"category":89,"tags":90},"\u002Fposts\u002Fjs-encoding-today","現在處理編碼：TextEncoder、Uint8Array 的 Base64 方法與 URLSearchParams","整理 JavaScript 現代編碼方式，使用 TextEncoder、TextDecoder 與 Uint8Array 處理 UTF-8 與 Base64，並說明 Base64URL、URLSearchParams 與 encodeURIComponent 的差異。","research",[91,92,93,94,95,18],"編碼","TextEncoder","Base64","URLSearchParams","Uint8Array",{"path":97,"title":98,"description":99,"category":16,"tags":100},"\u002Fposts\u002Fdart-sass-migration","Dart Sass 遷移筆記：node-sass 之後怎麼裝 Sass","node-sass 與 LibSass 已停止維護，現在改用 Dart Sass。整理 webpack 與 Vite 的安裝方式，以及為什麼不再像 node-sass 一樣容易遇到 Node.js 版本與原生編譯問題。",[101,102,103],"Sass","Webpack","Vite",{"path":105,"title":106,"description":107,"category":16,"tags":108},"\u002Fposts\u002Fdayjs-vue3-computed","day.js 搭配 Vue 3 的日期格式化","整理 Vue 3 日期格式化的常見做法，使用 day.js 取代舊專案常見的 moment.js，並以 method 或 computed 取代 Vue 2 filter，也補充原生 Intl.DateTimeFormat 的使用方式。",[44,109,110,111],"day.js","日期","Intl",{"path":113,"title":114,"description":115,"category":16,"tags":116},"\u002Fposts\u002Fes-modules-today","ES Module 現在的樣子：Node ESM、exports 與 import maps","整理現代 JavaScript ES Module 的常見用法，包括 Node.js 原生 ESM、package.json exports、瀏覽器 import maps、JSON import attributes，以及 Vite 動態載入的注意事項。",[117,118,119,120,103,18],"ES Module","Node.js","import maps","exports",{"path":122,"title":123,"description":124,"category":89,"tags":125},"\u002Fposts\u002Fstructured-clone","structuredClone()：終於有內建的深層拷貝","整理 JavaScript structuredClone() 的深層拷貝用法，說明 Date、Map、Set、循環參考的處理方式，以及 Function、class 與 Vue reactive Proxy 的注意事項。",[18,126,127,128],"structuredClone","深拷貝","Vue",{"path":130,"title":131,"description":132,"category":16,"tags":133},"\u002Fposts\u002Fdynamic-import","JavaScript 動態載入：import() 與 Vue 非同步元件","整理靜態 import、動態 import() 與 Vue defineAsyncComponent 的使用方式，並簡單補充 Vite import.meta.glob 的用途。",[18,134,135,103,136],"ES Modules","Vue 3","Code Splitting",{"path":138,"title":139,"description":140,"category":16,"tags":141},"\u002Fposts\u002Fscreen-wake-lock-api","Screen Wake Lock API：不用套件也能讓頁面保持亮著","整理 Screen Wake Lock API 的基本用法，說明 HTTPS、頁面可見性、切換分頁後重新取得 wake lock，以及 Vue／Nuxt 計時器使用時的注意事項。",[142,128,143,144,145,146],"Wake Lock","Nuxt4","行動裝置","計時器","Web API",{"path":148,"title":149,"description":150,"category":16,"tags":151},"\u002Fposts\u002Fhtml-meta-boilerplate-today","現在的 HTML meta 標籤怎麼寫","整理現在一個新頁面該有的 meta 標籤骨架——viewport 補上 viewport-fit=cover 因應瀏海與圓角螢幕、color-scheme 讓表單控制項跟著深色模式換色、theme-color 決定行動瀏覽器工具列顏色，以及基本的 SEO 與 Open Graph 標籤。",[152,153,154],"HTML","meta","SEO",{"path":156,"title":157,"description":158,"category":8,"tags":159},"\u002Fposts\u002Fdocker-node-postgres","把 Node + PostgreSQL 的 backend 裝進 Docker：Dockerfile、.dockerignore 與 compose","從「本機裝了就跑」到打包成容器的通用做法——Dockerfile 每一行的理由與 layer cache 為什麼決定了指令順序、.dockerignore 漏掉 node_modules 對原生模組是災難級的問題、容器之間為什麼不能用 localhost 互相找到對方，以及怎麼驗證資料真的寫進了 volume。",[160,161,118,162,163],"Docker","Docker Compose","PostgreSQL","Express",{"path":165,"title":166,"description":167,"category":16,"tags":168},"\u002Fposts\u002Fnuxt-server-proxy","Nuxt 3 \u002F 4 用 Server API 做代理與轉發","整理 Nuxt 3 與 Nuxt 4 使用 server\u002Fapi 轉發第三方 API 的方式，可以避免瀏覽器 CORS 問題、隱藏 API Key，也能在伺服器端加入快取。",[169,143,170,171,172],"Nuxt3","CORS","Nitro","API",{"path":174,"title":175,"description":176,"category":16,"tags":177},"\u002Fposts\u002Fnuxt4-project-setup","Nuxt 4 建立專案：和 Nuxt 3 有哪些不同","整理 Nuxt 4 建立專案的基本流程與目錄結構，並對照 Nuxt 3 的差異，包括 app\u002F 目錄、路徑別名、TypeScript，以及目前常用的 ESLint 與 Tailwind CSS 4 設定。",[143,44,178,179,180],"TypeScript","ESLint","Tailwind CSS 4",{"path":182,"title":183,"description":184,"category":16,"tags":185},"\u002Fposts\u002Fnuxt3-route-middleware","Nuxt 3 \u002F 4 的 Route Middleware：進頁面前先做判斷","整理 Nuxt 3 與 Nuxt 4 的 Route Middleware，用 defineNuxtRouteMiddleware 在進入頁面前檢查登入狀態，搭配 navigateTo 重新導向，並說明一般 middleware、global middleware 與 definePageMeta 的用法。",[169,143,186,187],"Middleware","驗證",{"path":189,"title":190,"description":191,"category":16,"tags":192},"\u002Fposts\u002Fnuxt-route-rules-redirect","Nuxt 3 \u002F 4 的 routeRules：重新導向與頁面設定","整理 Nuxt 3 與 Nuxt 4 的 routeRules 用法，可以依照不同網址設定重新導向、預渲染、SSR 與快取，並簡單對照 Nuxt 2 的舊做法。",[169,143,193,194],"routeRules","重新導向",{"path":196,"title":197,"description":198,"category":16,"tags":199},"\u002Fposts\u002Fios-iframe-google-login-blank-page","iOS iframe 串接 Google 登入出現空白頁：Popup 與頁面回收問題排查紀錄","記錄 iframe 內串接 Google 第三方登入時，部分 iOS 裝置因背景頁面遭到回收並重新載入，導致 Popup 登入流程中斷，以及最後透過 Redirect 分流與登入狀態接回機制處理的過程。",[73,200,201,202,203,204,205,206],"Safari","iframe","Google Login","GIS","OAuth","Popup","Redirect",{"path":208,"title":209,"description":210,"category":16,"tags":211},"\u002Fposts\u002Fios-login-tab-return-behavior","iOS 第三方登入後回不到原頁？分頁開啟關係與回頁行為實測","記錄 iOS Safari 與 Chrome 在多分頁第三方登入流程中，登入頁關閉後不一定回到原頁的實測，以及分頁開啟關係、window.close 與 window.focus 的限制。",[73,200,212,202,204,201,213,214],"Chrome","window.close","window.focus",{"path":216,"title":217,"description":218,"category":16,"tags":219},"\u002Fposts\u002Fgoogle-app-about-blank-placeholder","Google App 內建瀏覽器：about:blank 佔位頁被關閉的排查紀錄","記錄 iOS Google App 內建瀏覽器在非同步開啟外部頁面時，about:blank 佔位分頁被自動關閉，導致第三方登入或外部導轉失敗的排查與解法。",[73,220,221,222,204,223],"Google App","window.open","about:blank","WebView",{"path":225,"title":226,"description":227,"category":228,"tags":229},"\u002Fposts\u002Fclaude-code-codex-cli-init-basics","AI 相關紀錄 v1｜Claude Code \u002F Codex CLI 初始化與基本概念","從 Claude Code 與 Codex CLI 開始，整理 CLI、Coding Agent、Context、\u002Finit 與 CLAUDE.md／AGENTS.md 這幾個一開始最容易搞混的概念，以及在既有專案中的安裝與啟動方式。","ai",[230,231,232,233,234,235],"AI","Claude Code","Codex CLI","Coding Agent","CLAUDE.md","AGENTS.md",{"path":237,"title":238,"description":239,"category":228,"tags":240},"\u002Fposts\u002Fclaude-agents-md-project-guidelines","AI 相關紀錄 v2｜CLAUDE.md \u002F AGENTS.md 怎麼寫？專案規範與實際範例","整理 CLAUDE.md 與 AGENTS.md 的用途、適合記錄的專案規範，以及可直接參考的設定範例。",[230,231,232,234,235],{"path":242,"title":243,"description":244,"category":228,"tags":245},"\u002Fposts\u002Fclaude-codex-config-locations","AI 相關紀錄 v3｜Claude Code `.claude\u002F` \u002F Codex CLI 設定位置：全域與專案設定基本概要介紹","整理 Claude Code 與 Codex CLI 的使用者層級、專案層級設定位置，以及 rules、skills、agents 等目錄的用途。",[230,231,232,246],"設定檔",{"path":248,"title":249,"description":250,"category":228,"tags":251},"\u002Fposts\u002Fclaude-settings-codex-config","AI 相關紀錄 v4｜Claude Code settings \u002F Codex config 基本設定","整理 Claude Code settings.json 與 Codex config.toml 的設定層級、權限控制和常見基本設定。",[230,231,232,252,253],"settings.json","config.toml",{"path":255,"title":256,"description":257,"category":228,"tags":258},"\u002Fposts\u002Fclaude-codex-rules-structure","AI 相關紀錄 v5｜Rules：專案規則多了之後怎麼拆？","整理 Claude Code Rules 與 Codex AGENTS.md 的拆分方式，說明何時該拆、怎麼依目錄管理專案規則。",[230,231,232,259,235],"Rules",{"path":261,"title":262,"description":263,"category":228,"tags":264},"\u002Fposts\u002Fclaude-codex-slash-commands","AI 相關紀錄 v6｜Commands \u002F Slash Commands：CLI 裡的 `\u002F` 指令是什麼？","介紹 Claude Code 與 Codex CLI 的 Slash Commands，整理常用內建指令、自訂指令與 Skills 的差異。",[230,231,232,265],"Slash Commands",{"path":267,"title":268,"description":269,"category":228,"tags":270},"\u002Fposts\u002Fclaude-codex-skills","AI 相關紀錄 v7｜Skills：把重複工作流程整理起來","介紹 Claude Code 與 Codex Skills，整理適合保存成 Skill 的重複流程、基本結構與使用方式。",[230,231,232,271],"Skills",{"path":273,"title":274,"description":275,"category":228,"tags":276},"\u002Fposts\u002Fclaude-codex-agents-subagents","AI 相關紀錄 v8｜Agent \u002F Subagent：什麼時候真的需要分工？","整理 Agent、Subagent 與 Custom Agent 的用途，說明何時適合分工，以及它們和 Rules、Skills 的差異。",[230,231,232,277,278],"Agent","Subagent",{"path":280,"title":281,"description":282,"category":228,"tags":283},"\u002Fposts\u002Fmcp-basics","AI 相關紀錄 v9｜MCP：讓 AI 使用其他工具與資料","介紹 MCP 如何讓 AI 使用外部工具與資料，並以 Pencil MCP 說明實際用途、權限風險及與 Skill 的差異。",[230,284,231,232,285],"MCP","Pencil",{"path":287,"title":288,"description":289,"category":228,"tags":290},"\u002Fposts\u002Fai-coding-agent-concepts-summary","AI 相關紀錄 v10｜基本概念小結論","用一篇快速整理 CLAUDE.md、AGENTS.md、設定檔、Rules、Commands、Skills、Agent 與 MCP 的角色和差異。",[230,231,232,284,271,277],{"path":292,"title":293,"description":294,"category":228,"tags":295},"\u002Fposts\u002Fclaude-code-codex-model-selection","Claude Code 與 Codex：不同模型怎麼選？","比較 Claude Code 與 Codex 不同模型的速度、能力與成本取捨，依工作難度整理實用的選擇方向。",[230,231,296,297],"Codex","模型選擇",{"path":299,"title":300,"description":301,"category":228,"tags":302},"\u002Fposts\u002Fclaude-model-selection","Claude 模型簡單怎麼選？","整理 Claude 各模型在速度、能力與使用情境上的差異，提供從輕量工作到複雜任務的選擇方向。",[230,231,303,297],"Claude",{"path":305,"title":306,"description":307,"category":228,"tags":308},"\u002Fposts\u002Fcodex-model-selection","Codex 模型簡單怎麼選？","整理 Codex 各模型在速度、能力與使用情境上的差異，提供從簡單修改到大型端到端任務的選擇方向。",[230,296,309,297],"OpenAI",{"path":311,"title":312,"description":313,"category":228,"tags":314},"\u002Fposts\u002Fclaude-code-codex-cli-command-cheatsheet","Claude Code \u002F Codex CLI 常用指令速查表","整理 Claude Code 與 Codex CLI 的常用斜線指令、快捷操作與進階功能，方便需要時快速查找。",[230,231,232,265,315],"速查表",{"id":317,"title":123,"body":318,"category":89,"description":124,"draft":1717,"extension":1718,"image":1719,"meta":1720,"navigation":380,"path":122,"publishedAt":1721,"relatedExperiments":1722,"seo":1724,"stem":1725,"tags":1726,"updatedAt":1727,"__hash__":1728},"posts\u002Fposts\u002F20260415.structured-clone.md",{"type":319,"value":320,"toc":1706},"minimark",[321,325,414,418,421,516,523,526,563,580,583,602,606,609,806,809,883,890,893,899,902,942,945,965,972,976,978,1099,1102,1116,1123,1163,1168,1172,1179,1182,1233,1240,1288,1294,1357,1360,1387,1390,1399,1403,1530,1533,1536,1552,1554,1579,1582,1585,1609,1612,1615,1618,1634,1637,1660,1663,1666,1674,1677,1702],[322,323,324],"p",{},"JavaScript 的 Object、Array 是參考型資料。直接指定只會複製參考，兩個變數仍然指向同一份資料：",[326,327,332],"pre",{"className":328,"code":329,"language":330,"meta":331,"style":331},"language-js shiki shiki-themes github-light github-dark-default","const original = { name: 'Tom' }\nconst assigned = original\n\nassigned.name = 'John'\nconsole.log(original.name)\n\u002F\u002F 'John'\n","js","",[333,334,335,362,375,382,394,407],"code",{"__ignoreMap":331},[336,337,340,344,348,351,355,359],"span",{"class":338,"line":339},"line",1,[336,341,343],{"class":342},"sDgYj","const",[336,345,347],{"class":346},"sPgVT"," original",[336,349,350],{"class":342}," =",[336,352,354],{"class":353},"szmH1"," { name: ",[336,356,358],{"class":357},"sNbzA","'Tom'",[336,360,361],{"class":353}," }\n",[336,363,365,367,370,372],{"class":338,"line":364},2,[336,366,343],{"class":342},[336,368,369],{"class":346}," assigned",[336,371,350],{"class":342},[336,373,374],{"class":353}," original\n",[336,376,378],{"class":338,"line":377},3,[336,379,381],{"emptyLinePlaceholder":380},true,"\n",[336,383,385,388,391],{"class":338,"line":384},4,[336,386,387],{"class":353},"assigned.name ",[336,389,390],{"class":342},"=",[336,392,393],{"class":357}," 'John'\n",[336,395,397,400,404],{"class":338,"line":396},5,[336,398,399],{"class":353},"console.",[336,401,403],{"class":402},"sVjZL","log",[336,405,406],{"class":353},"(original.name)\n",[336,408,410],{"class":338,"line":409},6,[336,411,413],{"class":412},"sPyeA","\u002F\u002F 'John'\n",[415,416,417],"h2",{"id":417},"先分清楚淺層拷貝",[322,419,420],{},"展開運算子可以建立新的第一層物件，但巢狀物件仍然共用原本的參考：",[326,422,424],{"className":328,"code":423,"language":330,"meta":331,"style":331},"const original = {\n  name: 'Tom',\n  profile: { age: 20 }\n}\n\nconst shallow = { ...original }\nshallow.profile.age = 30\n\nconsole.log(original.profile.age)\n\u002F\u002F 30\n",[333,425,426,437,447,457,462,466,484,495,500,510],{"__ignoreMap":331},[336,427,428,430,432,434],{"class":338,"line":339},[336,429,343],{"class":342},[336,431,347],{"class":346},[336,433,350],{"class":342},[336,435,436],{"class":353}," {\n",[336,438,439,442,444],{"class":338,"line":364},[336,440,441],{"class":353},"  name: ",[336,443,358],{"class":357},[336,445,446],{"class":353},",\n",[336,448,449,452,455],{"class":338,"line":377},[336,450,451],{"class":353},"  profile: { age: ",[336,453,454],{"class":346},"20",[336,456,361],{"class":353},[336,458,459],{"class":338,"line":384},[336,460,461],{"class":353},"}\n",[336,463,464],{"class":338,"line":396},[336,465,381],{"emptyLinePlaceholder":380},[336,467,468,470,473,475,478,481],{"class":338,"line":409},[336,469,343],{"class":342},[336,471,472],{"class":346}," shallow",[336,474,350],{"class":342},[336,476,477],{"class":353}," { ",[336,479,480],{"class":342},"...",[336,482,483],{"class":353},"original }\n",[336,485,487,490,492],{"class":338,"line":486},7,[336,488,489],{"class":353},"shallow.profile.age ",[336,491,390],{"class":342},[336,493,494],{"class":346}," 30\n",[336,496,498],{"class":338,"line":497},8,[336,499,381],{"emptyLinePlaceholder":380},[336,501,503,505,507],{"class":338,"line":502},9,[336,504,399],{"class":353},[336,506,403],{"class":402},[336,508,509],{"class":353},"(original.profile.age)\n",[336,511,513],{"class":338,"line":512},10,[336,514,515],{"class":412},"\u002F\u002F 30\n",[322,517,518,519,522],{},"所以 ",[333,520,521],{},"{ ...object }"," 是淺層拷貝；需要讓巢狀資料也分開時，才是深層拷貝要處理的範圍。",[322,524,525],{},"以前想快速做深層拷貝，很常看到：",[326,527,529],{"className":328,"code":528,"language":330,"meta":331,"style":331},"const clone = JSON.parse(JSON.stringify(original))\n",[333,530,531],{"__ignoreMap":331},[336,532,533,535,538,540,543,546,549,552,555,557,560],{"class":338,"line":339},[336,534,343],{"class":342},[336,536,537],{"class":346}," clone",[336,539,350],{"class":342},[336,541,542],{"class":346}," JSON",[336,544,545],{"class":353},".",[336,547,548],{"class":402},"parse",[336,550,551],{"class":353},"(",[336,553,554],{"class":346},"JSON",[336,556,545],{"class":353},[336,558,559],{"class":402},"stringify",[336,561,562],{"class":353},"(original))\n",[322,564,565,566,569,570,569,573,569,576,579],{},"但這種方法遇到 ",[333,567,568],{},"Date","、",[333,571,572],{},"Map",[333,574,575],{},"Set",[333,577,578],{},"undefined"," 或循環參考時會有問題。",[322,581,582],{},"現在可以直接使用：",[326,584,586],{"className":328,"code":585,"language":330,"meta":331,"style":331},"const clone = structuredClone(original)\n",[333,587,588],{"__ignoreMap":331},[336,589,590,592,594,596,599],{"class":338,"line":339},[336,591,343],{"class":342},[336,593,537],{"class":346},[336,595,350],{"class":342},[336,597,598],{"class":402}," structuredClone",[336,600,601],{"class":353},"(original)\n",[415,603,605],{"id":604},"structuredclone-能處理什麼","structuredClone 能處理什麼",[322,607,608],{},"例如：",[326,610,612],{"className":328,"code":611,"language":330,"meta":331,"style":331},"const original = {\n  date: new Date(),\n  map: new Map([['name', '小明']]),\n  set: new Set([1, 2, 3]),\n  nested: {\n    value: 123\n  }\n}\n\nconst clone = structuredClone(original)\n\nclone.date instanceof Date\n\u002F\u002F true\n\nclone.map.get('name')\n\u002F\u002F '小明'\n\nclone.set.has(2)\n\u002F\u002F true\n",[333,613,614,624,638,663,692,697,705,710,714,718,730,735,748,754,759,775,781,786,801],{"__ignoreMap":331},[336,615,616,618,620,622],{"class":338,"line":339},[336,617,343],{"class":342},[336,619,347],{"class":346},[336,621,350],{"class":342},[336,623,436],{"class":353},[336,625,626,629,632,635],{"class":338,"line":364},[336,627,628],{"class":353},"  date: ",[336,630,631],{"class":342},"new",[336,633,634],{"class":402}," Date",[336,636,637],{"class":353},"(),\n",[336,639,640,643,645,648,651,654,657,660],{"class":338,"line":377},[336,641,642],{"class":353},"  map: ",[336,644,631],{"class":342},[336,646,647],{"class":402}," Map",[336,649,650],{"class":353},"([[",[336,652,653],{"class":357},"'name'",[336,655,656],{"class":353},", ",[336,658,659],{"class":357},"'小明'",[336,661,662],{"class":353},"]]),\n",[336,664,665,668,670,673,676,679,681,684,686,689],{"class":338,"line":384},[336,666,667],{"class":353},"  set: ",[336,669,631],{"class":342},[336,671,672],{"class":402}," Set",[336,674,675],{"class":353},"([",[336,677,678],{"class":346},"1",[336,680,656],{"class":353},[336,682,683],{"class":346},"2",[336,685,656],{"class":353},[336,687,688],{"class":346},"3",[336,690,691],{"class":353},"]),\n",[336,693,694],{"class":338,"line":396},[336,695,696],{"class":353},"  nested: {\n",[336,698,699,702],{"class":338,"line":409},[336,700,701],{"class":353},"    value: ",[336,703,704],{"class":346},"123\n",[336,706,707],{"class":338,"line":486},[336,708,709],{"class":353},"  }\n",[336,711,712],{"class":338,"line":497},[336,713,461],{"class":353},[336,715,716],{"class":338,"line":502},[336,717,381],{"emptyLinePlaceholder":380},[336,719,720,722,724,726,728],{"class":338,"line":512},[336,721,343],{"class":342},[336,723,537],{"class":346},[336,725,350],{"class":342},[336,727,598],{"class":402},[336,729,601],{"class":353},[336,731,733],{"class":338,"line":732},11,[336,734,381],{"emptyLinePlaceholder":380},[336,736,738,741,744],{"class":338,"line":737},12,[336,739,740],{"class":353},"clone.date ",[336,742,743],{"class":342},"instanceof",[336,745,747],{"class":746},"sYRkA"," Date\n",[336,749,751],{"class":338,"line":750},13,[336,752,753],{"class":412},"\u002F\u002F true\n",[336,755,757],{"class":338,"line":756},14,[336,758,381],{"emptyLinePlaceholder":380},[336,760,762,765,768,770,772],{"class":338,"line":761},15,[336,763,764],{"class":353},"clone.map.",[336,766,767],{"class":402},"get",[336,769,551],{"class":353},[336,771,653],{"class":357},[336,773,774],{"class":353},")\n",[336,776,778],{"class":338,"line":777},16,[336,779,780],{"class":412},"\u002F\u002F '小明'\n",[336,782,784],{"class":338,"line":783},17,[336,785,381],{"emptyLinePlaceholder":380},[336,787,789,792,795,797,799],{"class":338,"line":788},18,[336,790,791],{"class":353},"clone.set.",[336,793,794],{"class":402},"has",[336,796,551],{"class":353},[336,798,683],{"class":346},[336,800,774],{"class":353},[336,802,804],{"class":338,"line":803},19,[336,805,753],{"class":412},[322,807,808],{},"它也可以處理循環參考：",[326,810,812],{"className":328,"code":811,"language":330,"meta":331,"style":331},"const original = {\n  name: '小明'\n}\n\noriginal.self = original\n\nconst clone = structuredClone(original)\n\nclone.self === clone\n\u002F\u002F true\n",[333,813,814,824,831,835,839,848,852,864,868,879],{"__ignoreMap":331},[336,815,816,818,820,822],{"class":338,"line":339},[336,817,343],{"class":342},[336,819,347],{"class":346},[336,821,350],{"class":342},[336,823,436],{"class":353},[336,825,826,828],{"class":338,"line":364},[336,827,441],{"class":353},[336,829,830],{"class":357},"'小明'\n",[336,832,833],{"class":338,"line":377},[336,834,461],{"class":353},[336,836,837],{"class":338,"line":384},[336,838,381],{"emptyLinePlaceholder":380},[336,840,841,844,846],{"class":338,"line":396},[336,842,843],{"class":353},"original.self ",[336,845,390],{"class":342},[336,847,374],{"class":353},[336,849,850],{"class":338,"line":409},[336,851,381],{"emptyLinePlaceholder":380},[336,853,854,856,858,860,862],{"class":338,"line":486},[336,855,343],{"class":342},[336,857,537],{"class":346},[336,859,350],{"class":342},[336,861,598],{"class":402},[336,863,601],{"class":353},[336,865,866],{"class":338,"line":497},[336,867,381],{"emptyLinePlaceholder":380},[336,869,870,873,876],{"class":338,"line":502},[336,871,872],{"class":353},"clone.self ",[336,874,875],{"class":342},"===",[336,877,878],{"class":353}," clone\n",[336,880,881],{"class":338,"line":512},[336,882,753],{"class":412},[322,884,885,886,889],{},"這是 ",[333,887,888],{},"JSON.parse(JSON.stringify())"," 做不到的。",[415,891,892],{"id":892},"不能複製的東西",[322,894,895,898],{},[333,896,897],{},"structuredClone()"," 不是所有 JavaScript 物件都能複製。",[322,900,901],{},"例如函式：",[326,903,905],{"className":328,"code":904,"language":330,"meta":331,"style":331},"structuredClone({\n  fn: () => {}\n})\n\n\u002F\u002F DataCloneError\n",[333,906,907,914,928,933,937],{"__ignoreMap":331},[336,908,909,911],{"class":338,"line":339},[336,910,126],{"class":402},[336,912,913],{"class":353},"({\n",[336,915,916,919,922,925],{"class":338,"line":364},[336,917,918],{"class":402},"  fn",[336,920,921],{"class":353},": () ",[336,923,924],{"class":342},"=>",[336,926,927],{"class":353}," {}\n",[336,929,930],{"class":338,"line":377},[336,931,932],{"class":353},"})\n",[336,934,935],{"class":338,"line":384},[336,936,381],{"emptyLinePlaceholder":380},[336,938,939],{"class":338,"line":396},[336,940,941],{"class":412},"\u002F\u002F DataCloneError\n",[322,943,944],{},"DOM 節點也不行：",[326,946,948],{"className":328,"code":947,"language":330,"meta":331,"style":331},"structuredClone(document.body)\n\n\u002F\u002F DataCloneError\n",[333,949,950,957,961],{"__ignoreMap":331},[336,951,952,954],{"class":338,"line":339},[336,953,126],{"class":402},[336,955,956],{"class":353},"(document.body)\n",[336,958,959],{"class":338,"line":364},[336,960,381],{"emptyLinePlaceholder":380},[336,962,963],{"class":338,"line":377},[336,964,941],{"class":412},[322,966,967,968,971],{},"如果資料裡包含不能複製的內容，它會直接丟出 ",[333,969,970],{},"DataCloneError","。",[415,973,975],{"id":974},"class-不會保留原型","class 不會保留原型",[322,977,608],{},[326,979,981],{"className":328,"code":980,"language":330,"meta":331,"style":331},"class User {\n  constructor(name) {\n    this.name = name\n  }\n\n  greet() {\n    return `Hi ${this.name}`\n  }\n}\n\nconst user = new User('小明')\nconst clone = structuredClone(user)\n",[333,982,983,993,1007,1020,1024,1028,1036,1054,1058,1062,1066,1086],{"__ignoreMap":331},[336,984,985,988,991],{"class":338,"line":339},[336,986,987],{"class":342},"class",[336,989,990],{"class":746}," User",[336,992,436],{"class":353},[336,994,995,998,1000,1004],{"class":338,"line":364},[336,996,997],{"class":342},"  constructor",[336,999,551],{"class":353},[336,1001,1003],{"class":1002},"sjlk-","name",[336,1005,1006],{"class":353},") {\n",[336,1008,1009,1012,1015,1017],{"class":338,"line":377},[336,1010,1011],{"class":346},"    this",[336,1013,1014],{"class":353},".name ",[336,1016,390],{"class":342},[336,1018,1019],{"class":353}," name\n",[336,1021,1022],{"class":338,"line":384},[336,1023,709],{"class":353},[336,1025,1026],{"class":338,"line":396},[336,1027,381],{"emptyLinePlaceholder":380},[336,1029,1030,1033],{"class":338,"line":409},[336,1031,1032],{"class":402},"  greet",[336,1034,1035],{"class":353},"() {\n",[336,1037,1038,1041,1044,1047,1049,1051],{"class":338,"line":486},[336,1039,1040],{"class":342},"    return",[336,1042,1043],{"class":357}," `Hi ${",[336,1045,1046],{"class":346},"this",[336,1048,545],{"class":357},[336,1050,1003],{"class":353},[336,1052,1053],{"class":357},"}`\n",[336,1055,1056],{"class":338,"line":497},[336,1057,709],{"class":353},[336,1059,1060],{"class":338,"line":502},[336,1061,461],{"class":353},[336,1063,1064],{"class":338,"line":512},[336,1065,381],{"emptyLinePlaceholder":380},[336,1067,1068,1070,1073,1075,1078,1080,1082,1084],{"class":338,"line":732},[336,1069,343],{"class":342},[336,1071,1072],{"class":346}," user",[336,1074,350],{"class":342},[336,1076,1077],{"class":342}," new",[336,1079,990],{"class":402},[336,1081,551],{"class":353},[336,1083,659],{"class":357},[336,1085,774],{"class":353},[336,1087,1088,1090,1092,1094,1096],{"class":338,"line":737},[336,1089,343],{"class":342},[336,1091,537],{"class":346},[336,1093,350],{"class":342},[336,1095,598],{"class":402},[336,1097,1098],{"class":353},"(user)\n",[322,1100,1101],{},"資料還在：",[326,1103,1105],{"className":328,"code":1104,"language":330,"meta":331,"style":331},"clone.name\n\u002F\u002F '小明'\n",[333,1106,1107,1112],{"__ignoreMap":331},[336,1108,1109],{"class":338,"line":339},[336,1110,1111],{"class":353},"clone.name\n",[336,1113,1114],{"class":338,"line":364},[336,1115,780],{"class":412},[322,1117,1118,1119,1122],{},"但它不再是原本的 ",[333,1120,1121],{},"User","：",[326,1124,1126],{"className":328,"code":1125,"language":330,"meta":331,"style":331},"clone instanceof User\n\u002F\u002F false\n\nclone.greet()\n\u002F\u002F TypeError\n",[333,1127,1128,1138,1143,1147,1158],{"__ignoreMap":331},[336,1129,1130,1133,1135],{"class":338,"line":339},[336,1131,1132],{"class":353},"clone ",[336,1134,743],{"class":342},[336,1136,1137],{"class":746}," User\n",[336,1139,1140],{"class":338,"line":364},[336,1141,1142],{"class":412},"\u002F\u002F false\n",[336,1144,1145],{"class":338,"line":377},[336,1146,381],{"emptyLinePlaceholder":380},[336,1148,1149,1152,1155],{"class":338,"line":384},[336,1150,1151],{"class":353},"clone.",[336,1153,1154],{"class":402},"greet",[336,1156,1157],{"class":353},"()\n",[336,1159,1160],{"class":338,"line":396},[336,1161,1162],{"class":412},"\u002F\u002F TypeError\n",[322,1164,518,1165,1167],{},[333,1166,897],{}," 比較適合複製「資料」，不是複製帶有行為的 class instance。",[415,1169,1171],{"id":1170},"vue-reactive-的注意事項","Vue reactive 的注意事項",[322,1173,1174,1175,1178],{},"Vue 的 ",[333,1176,1177],{},"reactive()"," 回傳的是 Proxy。",[322,1180,1181],{},"因此不能直接：",[326,1183,1185],{"className":328,"code":1184,"language":330,"meta":331,"style":331},"const state = reactive({\n  name: '小明',\n  items: []\n})\n\nstructuredClone(state)\n\u002F\u002F DataCloneError\n",[333,1186,1187,1201,1209,1214,1218,1222,1229],{"__ignoreMap":331},[336,1188,1189,1191,1194,1196,1199],{"class":338,"line":339},[336,1190,343],{"class":342},[336,1192,1193],{"class":346}," state",[336,1195,350],{"class":342},[336,1197,1198],{"class":402}," reactive",[336,1200,913],{"class":353},[336,1202,1203,1205,1207],{"class":338,"line":364},[336,1204,441],{"class":353},[336,1206,659],{"class":357},[336,1208,446],{"class":353},[336,1210,1211],{"class":338,"line":377},[336,1212,1213],{"class":353},"  items: []\n",[336,1215,1216],{"class":338,"line":384},[336,1217,932],{"class":353},[336,1219,1220],{"class":338,"line":396},[336,1221,381],{"emptyLinePlaceholder":380},[336,1223,1224,1226],{"class":338,"line":409},[336,1225,126],{"class":402},[336,1227,1228],{"class":353},"(state)\n",[336,1230,1231],{"class":338,"line":486},[336,1232,941],{"class":412},[322,1234,1235,1236,1239],{},"可以先使用 ",[333,1237,1238],{},"toRaw()"," 取得原始物件：",[326,1241,1243],{"className":328,"code":1242,"language":330,"meta":331,"style":331},"import { toRaw } from 'vue'\n\nconst snapshot = structuredClone(\n  toRaw(state)\n)\n",[333,1244,1245,1259,1263,1277,1284],{"__ignoreMap":331},[336,1246,1247,1250,1253,1256],{"class":338,"line":339},[336,1248,1249],{"class":342},"import",[336,1251,1252],{"class":353}," { toRaw } ",[336,1254,1255],{"class":342},"from",[336,1257,1258],{"class":357}," 'vue'\n",[336,1260,1261],{"class":338,"line":364},[336,1262,381],{"emptyLinePlaceholder":380},[336,1264,1265,1267,1270,1272,1274],{"class":338,"line":377},[336,1266,343],{"class":342},[336,1268,1269],{"class":346}," snapshot",[336,1271,350],{"class":342},[336,1273,598],{"class":402},[336,1275,1276],{"class":353},"(\n",[336,1278,1279,1282],{"class":338,"line":384},[336,1280,1281],{"class":402},"  toRaw",[336,1283,1228],{"class":353},[336,1285,1286],{"class":338,"line":396},[336,1287,774],{"class":353},[322,1289,1290,1291,1122],{},"如果使用 ",[333,1292,1293],{},"ref()",[326,1295,1297],{"className":328,"code":1296,"language":330,"meta":331,"style":331},"const form = ref({\n  name: '',\n  items: []\n})\n\nconst snapshot = structuredClone(\n  toRaw(form.value)\n)\n",[333,1298,1299,1313,1322,1326,1330,1334,1346,1353],{"__ignoreMap":331},[336,1300,1301,1303,1306,1308,1311],{"class":338,"line":339},[336,1302,343],{"class":342},[336,1304,1305],{"class":346}," form",[336,1307,350],{"class":342},[336,1309,1310],{"class":402}," ref",[336,1312,913],{"class":353},[336,1314,1315,1317,1320],{"class":338,"line":364},[336,1316,441],{"class":353},[336,1318,1319],{"class":357},"''",[336,1321,446],{"class":353},[336,1323,1324],{"class":338,"line":377},[336,1325,1213],{"class":353},[336,1327,1328],{"class":338,"line":384},[336,1329,932],{"class":353},[336,1331,1332],{"class":338,"line":396},[336,1333,381],{"emptyLinePlaceholder":380},[336,1335,1336,1338,1340,1342,1344],{"class":338,"line":409},[336,1337,343],{"class":342},[336,1339,1269],{"class":346},[336,1341,350],{"class":342},[336,1343,598],{"class":402},[336,1345,1276],{"class":353},[336,1347,1348,1350],{"class":338,"line":486},[336,1349,1281],{"class":402},[336,1351,1352],{"class":353},"(form.value)\n",[336,1354,1355],{"class":338,"line":497},[336,1356,774],{"class":353},[322,1358,1359],{},"這很適合用在表單編輯，例如先保存一份原始資料：",[326,1361,1363],{"className":328,"code":1362,"language":330,"meta":331,"style":331},"const original = structuredClone(\n  toRaw(form.value)\n)\n",[333,1364,1365,1377,1383],{"__ignoreMap":331},[336,1366,1367,1369,1371,1373,1375],{"class":338,"line":339},[336,1368,343],{"class":342},[336,1370,347],{"class":346},[336,1372,350],{"class":342},[336,1374,598],{"class":402},[336,1376,1276],{"class":353},[336,1378,1379,1381],{"class":338,"line":364},[336,1380,1281],{"class":402},[336,1382,1352],{"class":353},[336,1384,1385],{"class":338,"line":377},[336,1386,774],{"class":353},[322,1388,1389],{},"取消編輯時就可以拿這份資料還原。",[322,1391,1392,1393,1395,1396,1398],{},"需要注意，如果物件內部本來就另外塞入其他 ",[333,1394,1177],{}," 建立的 Proxy，單純 ",[333,1397,1238],{}," 最外層仍可能不夠。",[415,1400,1402],{"id":1401},"和-json-深拷貝的差異","和 JSON 深拷貝的差異",[1404,1405,1406,1421],"table",{},[1407,1408,1409],"thead",{},[1410,1411,1412,1416,1419],"tr",{},[1413,1414,1415],"th",{},"資料",[1413,1417,1418],{},"JSON 方法",[1413,1420,126],{},[1422,1423,1424,1435,1447,1461,1472,1490,1500,1510,1520],"tbody",{},[1410,1425,1426,1430,1433],{},[1427,1428,1429],"td",{},"一般 Object \u002F Array",[1427,1431,1432],{},"可以",[1427,1434,1432],{},[1410,1436,1437,1441,1444],{},[1427,1438,1439],{},[333,1440,568],{},[1427,1442,1443],{},"變字串",[1427,1445,1446],{},"保留",[1410,1448,1449,1456,1459],{},[1427,1450,1451,1453,1454],{},[333,1452,572],{}," \u002F ",[333,1455,575],{},[1427,1457,1458],{},"無法正常保留",[1427,1460,1446],{},[1410,1462,1463,1467,1470],{},[1427,1464,1465],{},[333,1466,578],{},[1427,1468,1469],{},"可能消失",[1427,1471,1446],{},[1410,1473,1474,1482,1488],{},[1427,1475,1476,1453,1479],{},[333,1477,1478],{},"NaN",[333,1480,1481],{},"Infinity",[1427,1483,1484,1485],{},"變 ",[333,1486,1487],{},"null",[1427,1489,1446],{},[1410,1491,1492,1495,1498],{},[1427,1493,1494],{},"循環參考",[1427,1496,1497],{},"Error",[1427,1499,1432],{},[1410,1501,1502,1505,1508],{},[1427,1503,1504],{},"Function",[1427,1506,1507],{},"消失或無法處理",[1427,1509,970],{},[1410,1511,1512,1515,1518],{},[1427,1513,1514],{},"class 原型",[1427,1516,1517],{},"不保留",[1427,1519,1517],{},[1410,1521,1522,1525,1528],{},[1427,1523,1524],{},"Vue Proxy",[1427,1526,1527],{},"無法正常使用",[1427,1529,970],{},[415,1531,1532],{"id":1532},"什麼時候使用",[322,1534,1535],{},"一般資料要做深層拷貝時，可以優先考慮：",[326,1537,1538],{"className":328,"code":585,"language":330,"meta":331,"style":331},[333,1539,1540],{"__ignoreMap":331},[336,1541,1542,1544,1546,1548,1550],{"class":338,"line":339},[336,1543,343],{"class":342},[336,1545,537],{"class":346},[336,1547,350],{"class":342},[336,1549,598],{"class":402},[336,1551,601],{"class":353},[322,1553,608],{},[1555,1556,1557,1561,1564,1567,1576],"ul",{},[1558,1559,1560],"li",{},"複製 API 回傳資料",[1558,1562,1563],{},"保存表單修改前的狀態",[1558,1565,1566],{},"複製巢狀 Object \u002F Array",[1558,1568,1569,1570,569,1572,569,1574],{},"資料包含 ",[333,1571,568],{},[333,1573,572],{},[333,1575,575],{},[1558,1577,1578],{},"資料可能有循環參考",[322,1580,1581],{},"如果物件包含 Function、特殊 class 行為或 Vue Proxy，就需要另外處理。",[322,1583,1584],{},"而：",[326,1586,1588],{"className":328,"code":1587,"language":330,"meta":331,"style":331},"JSON.parse(JSON.stringify(value))\n",[333,1589,1590],{"__ignoreMap":331},[336,1591,1592,1594,1596,1598,1600,1602,1604,1606],{"class":338,"line":339},[336,1593,554],{"class":346},[336,1595,545],{"class":353},[336,1597,548],{"class":402},[336,1599,551],{"class":353},[336,1601,554],{"class":346},[336,1603,545],{"class":353},[336,1605,559],{"class":402},[336,1607,1608],{"class":353},"(value))\n",[322,1610,1611],{},"比較適合真的要確認「JSON 序列化之後會長什麼樣子」的場合，而不是拿來當通用深層拷貝工具。",[415,1613,1614],{"id":1614},"小結",[322,1616,1617],{},"現在需要複製一般 JavaScript 資料，可以先想到：",[326,1619,1620],{"className":328,"code":585,"language":330,"meta":331,"style":331},[333,1621,1622],{"__ignoreMap":331},[336,1623,1624,1626,1628,1630,1632],{"class":338,"line":339},[336,1625,343],{"class":342},[336,1627,537],{"class":346},[336,1629,350],{"class":342},[336,1631,598],{"class":402},[336,1633,601],{"class":353},[322,1635,1636],{},"它比：",[326,1638,1640],{"className":328,"code":1639,"language":330,"meta":331,"style":331},"JSON.parse(JSON.stringify(original))\n",[333,1641,1642],{"__ignoreMap":331},[336,1643,1644,1646,1648,1650,1652,1654,1656,1658],{"class":338,"line":339},[336,1645,554],{"class":346},[336,1647,545],{"class":353},[336,1649,548],{"class":402},[336,1651,551],{"class":353},[336,1653,554],{"class":346},[336,1655,545],{"class":353},[336,1657,559],{"class":402},[336,1659,562],{"class":353},[322,1661,1662],{},"能正確處理更多 JavaScript 資料型別。",[322,1664,1665],{},"但要記住三個限制：",[326,1667,1672],{"className":1668,"code":1670,"language":1671,"meta":331},[1669],"language-text","Function → 不行\nclass prototype → 不保留\nVue reactive Proxy → 先 toRaw()\n","text",[333,1673,1670],{"__ignoreMap":331},[415,1675,1676],{"id":1676},"參考資料",[1555,1678,1679,1688,1695],{},[1558,1680,1681],{},[1682,1683,1687],"a",{"href":1684,"rel":1685},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FWindow\u002FstructuredClone",[1686],"nofollow","MDN：structuredClone()",[1558,1689,1690],{},[1682,1691,1694],{"href":1692,"rel":1693},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FWeb_Workers_API\u002FStructured_clone_algorithm",[1686],"MDN：Structured clone algorithm",[1558,1696,1697],{},[1682,1698,1701],{"href":1699,"rel":1700},"https:\u002F\u002Fvuejs.org\u002Fapi\u002Freactivity-advanced.html#toraw",[1686],"Vue：toRaw()",[1703,1704,1705],"style",{},"html pre.shiki code .sDgYj, html code.shiki .sDgYj{--shiki-default:#D73A49;--shiki-dark:#FF7B72}html pre.shiki code .sPgVT, html code.shiki .sPgVT{--shiki-default:#005CC5;--shiki-dark:#79C0FF}html pre.shiki code .szmH1, html code.shiki .szmH1{--shiki-default:#24292E;--shiki-dark:#E6EDF3}html pre.shiki code .sNbzA, html code.shiki .sNbzA{--shiki-default:#032F62;--shiki-dark:#A5D6FF}html pre.shiki code .sVjZL, html code.shiki .sVjZL{--shiki-default:#6F42C1;--shiki-dark:#D2A8FF}html pre.shiki code .sPyeA, html code.shiki .sPyeA{--shiki-default:#6A737D;--shiki-dark:#8B949E}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sYRkA, html code.shiki .sYRkA{--shiki-default:#6F42C1;--shiki-dark:#FFA657}html pre.shiki code .sjlk-, html code.shiki .sjlk-{--shiki-default:#E36209;--shiki-dark:#FFA657}",{"title":331,"searchDepth":377,"depth":377,"links":1707},[1708,1709,1710,1711,1712,1713,1714,1715,1716],{"id":417,"depth":364,"text":417},{"id":604,"depth":364,"text":605},{"id":892,"depth":364,"text":892},{"id":974,"depth":364,"text":975},{"id":1170,"depth":364,"text":1171},{"id":1401,"depth":364,"text":1402},{"id":1532,"depth":364,"text":1532},{"id":1614,"depth":364,"text":1614},{"id":1676,"depth":364,"text":1676},false,"md",null,{},"2026-04-15",[1723],"json-formatter",{"title":123,"description":124},"posts\u002F20260415.structured-clone",[18,126,127,128],"2026-09-08","TQqElx4qPVv1CJdG52c71VuL1EgpkyVH55XQ3e7U3FE",[1730,1733],{"title":131,"path":130,"stem":1731,"description":132,"category":16,"publishedAt":1732,"children":-1},"posts\u002F20260417.dynamic-import","2026-04-17",{"title":114,"path":113,"stem":1734,"description":115,"category":16,"publishedAt":1735,"children":-1},"posts\u002F20260414.es-modules-today","2026-04-14",1791786901254]