首页 文章 精选 留言 我的

精选列表

搜索[javascript],共10000篇文章
优秀的个人博客,低调大师

JavaScript 中 AbortController 的中断请求与事件监听清理实战

最近在排查一个后台管理系统里偶发的内存泄漏问题时,发现几个页面在快速切换菜单后,仍然有未完成的 fetch 请求在持续占用资源,甚至触发了 setState 警告。这类场景其实很常见:用户点击某个按钮发起数据请求,还没等响应回来就跳走了,或者连续触发了多个相同请求,旧请求返回后覆盖了新数据。以前我们习惯用 axios 的 CancelToken 或者自己维护一个 flag 来判断是否忽略结果,但这只是“忽略”,请求本身并没有被真正取消,浏览器的网络连接依然存在。AbortController 提供了一种更标准的取消机制,不仅能中断 fetch,还能移除事件监听器,甚至配合自定义异步任务使用。这篇内容会从实际代码出发,梳理 AbortController 的基本用法、在请求竞态和组件卸载时的处理方式,以及如何结合事件监听器避免重复绑定带来的泄漏。 先看一个最基础的例子。fetch 接受一个 signal 参数,这个 signal 来自 AbortController 实例。调用 controller.abort() 之后,进行中的 fetch 会直接 reject 一个 AbortError。 ```js const controller = new AbortController(); const { signal } = controller; fetch('/api/users', { signal }) .then(res => res.json()) .then(data => console.log(data)) .catch(err => { if (err.name === 'AbortError') { console.log('请求被取消'); } else { console.error('请求失败', err); } }); // 在需要取消的时候调用 controller.abort(); ``` 这里有个细节:abort() 之后 signal 会变成 aborted 状态,并且不会再恢复。如果同一个 controller 再次用于新的 fetch,会立刻抛出 AbortError。所以每次请求都应该创建新的 AbortController 实例。 实际项目中更常见的是搜索框联想功能。用户每输入一个字符就发一次请求,但只有最后一次输入的结果需要展示。如果不做取消,旧请求可能后返回,导致列表内容闪烁或者显示错误结果。 ```js let currentController = null; async function search(keyword) { if (currentController) { currentController.abort(); } currentController = new AbortController(); try { const res = await fetch(`/api/search?q=${encodeURIComponent(keyword)}`, { signal: currentController.signal }); const data = await res.json(); renderList(data); } catch (err) { if (err.name !== 'AbortError') { showError(err); } } finally { currentController = null; } } ``` 这里用 currentController 保存最近一次的控制器,新请求发起前先取消旧的。注意在 finally 里把 currentController 置空,避免在快速连续调用时错误地取消已经完成的请求。 在 React 或 Vue 组件里,经常遇到组件卸载后请求才返回,然后调用 setState 或者修改响应式数据,造成警告甚至内存泄漏。以前的做法是在组件里维护一个 isMounted 变量,但 AbortController 更彻底。以 React 函数组件为例: ```js import { useEffect, useState } from 'react'; function UserProfile({ userId }) { const [user, setUser] = useState(null); useEffect(() => { const controller = new AbortController(); fetch(`/api/users/${userId}`, { signal: controller.signal }) .then(res => res.json()) .then(data => setUser(data)) .catch(err => { if (err.name !== 'AbortError') { console.error(err); } }); return () => { controller.abort(); }; }, [userId]); if (!user) return Loading...; return {user.name}; } ``` 当 userId 变化或者组件卸载时,useEffect 的清理函数会调用 abort(),请求被取消,后面的 then 不会执行,setUser 也不会被调用。这样就不需要手动维护 isMounted 标志了。 AbortController 的另一个实用场景是移除事件监听器。addEventListener 支持传入一个 signal,当 signal 被 abort 时,监听器会自动移除。这在需要动态绑定和解绑大量事件时特别省心。 ```js const controller = new AbortController(); const { signal } = controller; window.addEventListener('resize', handleResize, { signal }); window.addEventListener('scroll', handleScroll, { signal }); document.getElementById('btn').addEventListener('click', handleClick, { signal }); // 需要清理的时候 controller.abort(); ``` 如果不使用 signal,就必须记住每个监听器的引用以及对应的元素,分别调用 removeEventListener。现在一个 abort() 就能全部移除。在单页应用里,页面切换时清理全局事件监听特别有用。 有时候我们需要把 AbortController 和自定义的异步任务结合。比如封装一个支持取消的延时函数: ```js function delay(ms, signal) { return new Promise((resolve, reject) => { const timer = setTimeout(resolve, ms); if (signal) { if (signal.aborted) { clearTimeout(timer); reject(new DOMException('Aborted', 'AbortError')); return; } signal.addEventListener('abort', () => { clearTimeout(timer); reject(new DOMException('Aborted', 'AbortError')); }, { once: true }); } }); } ``` 这样调用方就可以用同一个 signal 统一取消多个异步操作。注意这里用了 DOMException 来模拟原生 AbortError 的行为,方便上层统一处理。 另一个容易踩坑的地方是,abort() 之后 signal 上的 abort 事件只会触发一次。如果需要在取消后执行清理逻辑,应该监听 abort 事件而不是在 catch 里做所有事情。 ```js const controller = new AbortController(); const { signal } = controller; signal.addEventListener('abort', () => { console.log('取消发生了,清理资源'); }, { once: true }); ``` 比如上传文件时,可以在 abort 事件里清理临时文件或者关闭 WebSocket 连接。 还有一点,AbortController 不能直接取消已经完成的请求,也不会影响已经 resolve 的 Promise。所以如果请求已经成功返回,再调用 abort() 不会有任何效果。这其实符合预期,不需要额外判断。 在 Node.js 环境中,从 v15 开始也支持 AbortController,可以用于中断 http 请求或者自定义流。比如使用 undici 或者 node-fetch 时,同样可以传入 signal。 ```js const { request } = require('undici'); const controller = new AbortController(); request('http://example.com', { signal: controller.signal }) .then(({ statusCode, body }) => { // 处理响应 }) .catch(err => { if (err.name === 'AbortError') { console.log('请求中止'); } }); setTimeout(() => controller.abort(), 1000); ``` 如果项目里还在用 axios,它从 v0.22.0 开始也支持 AbortController 作为 cancelToken 的替代方案。迁移时只需要把 CancelToken.source() 换成 new AbortController(),然后把 signal 传给请求配置即可。 ```js const controller = new AbortController(); axios.get('/api/data', { signal: controller.signal }).catch(err => { if (axios.isCancel(err)) { console.log('请求取消'); } }); controller.abort(); ``` axios 内部会把 AbortError 转换成自己的 Cancel 错误,用 axios.isCancel 判断更准确。 实际开发中,把 AbortController 和请求库结合时,注意不要在组件卸载后还去访问已经废弃的状态。虽然 abort 能阻止 then 执行,但如果代码里用了 async/await 并且没有正确处理异常,仍然可能走到后面的逻辑。最好在 catch 里判断错误类型,只处理非取消的错误。 最后提一下兼容性。AbortController 在现代浏览器中支持已经很好,Chrome 66+、Firefox 57+、Safari 12.1+ 都支持。如果还需要支持 IE,就只能用 polyfill 或者继续用旧的取消方案。不过现在大部分项目已经不需要考虑 IE 了。 推荐查看天气:http://www.362tq.com/heshuo/40tian.html 推荐查看天气:http://www.362tq.com/bohu/ 推荐查看天气:http://www.362tq.com/bohu/zuotian.html 推荐查看天气:http://www.362tq.com/bohu/7tian.html 推荐查看天气:http://www.362tq.com/bohu/10tian.html 推荐查看天气:http://www.362tq.com/bohu/15tian.html 推荐查看天气:http://www.362tq.com/bohu/40tian.html 推荐查看天气:http://www.362tq.com/akesu/ 推荐查看天气:http://www.362tq.com/akesu/zuotian.html 推荐查看天气:http://www.362tq.com/akesu/7tian.html 推荐查看天气:http://www.362tq.com/akesu/10tian.html 推荐查看天气:http://www.362tq.com/akesu/15tian.html 推荐查看天气:http://www.362tq.com/akesu/40tian.html 推荐查看天气:http://www.362tq.com/wensu/ 推荐查看天气:http://www.362tq.com/wensu/zuotian.html 推荐查看天气:http://www.362tq.com/wensu/7tian.html 推荐查看天气:http://www.362tq.com/wensu/10tian.html 推荐查看天气:http://www.362tq.com/wensu/15tian.html 推荐查看天气:http://www.362tq.com/wensu/40tian.html 推荐查看天气:http://www.362tq.com/kuche/ 推荐查看天气:http://www.362tq.com/kuche/zuotian.html 推荐查看天气:http://www.362tq.com/kuche/7tian.html 推荐查看天气:http://www.362tq.com/kuche/10tian.html 推荐查看天气:http://www.362tq.com/kuche/15tian.html 推荐查看天气:http://www.362tq.com/kuche/40tian.html 推荐查看天气:http://www.362tq.com/shaya/ 推荐查看天气:http://www.362tq.com/shaya/zuotian.html 推荐查看天气:http://www.362tq.com/shaya/7tian.html 推荐查看天气:http://www.362tq.com/shaya/10tian.html 推荐查看天气:http://www.362tq.com/shaya/15tian.html 推荐查看天气:http://www.362tq.com/shaya/40tian.html 推荐查看天气:http://www.362tq.com/xinhe/ 推荐查看天气:http://www.362tq.com/xinhe/zuotian.html 推荐查看天气:http://www.362tq.com/xinhe/7tian.html 推荐查看天气:http://www.362tq.com/xinhe/10tian.html 推荐查看天气:http://www.362tq.com/xinhe/15tian.html 推荐查看天气:http://www.362tq.com/xinhe/40tian.html 推荐查看天气:http://www.362tq.com/baichengxian/ 推荐查看天气:http://www.362tq.com/baichengxian/zuotian.html 推荐查看天气:http://www.362tq.com/baichengxian/7tian.html 推荐查看天气:http://www.362tq.com/baichengxian/10tian.html 推荐查看天气:http://www.362tq.com/baichengxian/15tian.html 推荐查看天气:http://www.362tq.com/baichengxian/40tian.html 推荐查看天气:http://www.362tq.com/wushi/ 推荐查看天气:http://www.362tq.com/wushi/zuotian.html 推荐查看天气:http://www.362tq.com/wushi/7tian.html 推荐查看天气:http://www.362tq.com/wushi/10tian.html 推荐查看天气:http://www.362tq.com/wushi/15tian.html 推荐查看天气:http://www.362tq.com/wushi/40tian.html 推荐查看天气:http://www.362tq.com/awati/ 推荐查看天气:http://www.362tq.com/awati/zuotian.html 推荐查看天气:http://www.362tq.com/awati/7tian.html 推荐查看天气:http://www.362tq.com/awati/10tian.html 推荐查看天气:http://www.362tq.com/awati/15tian.html 推荐查看天气:http://www.362tq.com/awati/40tian.html 推荐查看天气:http://www.362tq.com/keping/ 推荐查看天气:http://www.362tq.com/keping/zuotian.html 推荐查看天气:http://www.362tq.com/keping/7tian.html 推荐查看天气:http://www.362tq.com/keping/10tian.html 推荐查看天气:http://www.362tq.com/keping/15tian.html 推荐查看天气:http://www.362tq.com/keping/40tian.html 推荐查看天气:http://www.362tq.com/kezhou/ 推荐查看天气:http://www.362tq.com/kezhou/zuotian.html 推荐查看天气:http://www.362tq.com/kezhou/7tian.html 推荐查看天气:http://www.362tq.com/kezhou/10tian.html 推荐查看天气:http://www.362tq.com/kezhou/15tian.html 推荐查看天气:http://www.362tq.com/kezhou/40tian.html 推荐查看天气:http://www.362tq.com/atushi/ 推荐查看天气:http://www.362tq.com/atushi/zuotian.html 推荐查看天气:http://www.362tq.com/atushi/7tian.html 推荐查看天气:http://www.362tq.com/atushi/10tian.html 推荐查看天气:http://www.362tq.com/atushi/15tian.html 推荐查看天气:http://www.362tq.com/atushi/40tian.html 推荐查看天气:http://www.362tq.com/aketao/ 推荐查看天气:http://www.362tq.com/aketao/zuotian.html 推荐查看天气:http://www.362tq.com/aketao/7tian.html 推荐查看天气:http://www.362tq.com/aketao/10tian.html 推荐查看天气:http://www.362tq.com/aketao/15tian.html 推荐查看天气:http://www.362tq.com/aketao/40tian.html 推荐查看天气:http://www.362tq.com/aheqi/ 推荐查看天气:http://www.362tq.com/aheqi/zuotian.html 推荐查看天气:http://www.362tq.com/aheqi/7tian.html 推荐查看天气:http://www.362tq.com/aheqi/10tian.html 推荐查看天气:http://www.362tq.com/aheqi/15tian.html 推荐查看天气:http://www.362tq.com/aheqi/40tian.html 推荐查看天气:http://www.362tq.com/wuqia/ 推荐查看天气:http://www.362tq.com/wuqia/zuotian.html 推荐查看天气:http://www.362tq.com/wuqia/7tian.html 推荐查看天气:http://www.362tq.com/wuqia/10tian.html 推荐查看天气:http://www.362tq.com/wuqia/15tian.html 推荐查看天气:http://www.362tq.com/wuqia/40tian.html 推荐查看天气:http://www.362tq.com/kashi/ 推荐查看天气:http://www.362tq.com/kashi/zuotian.html 推荐查看天气:http://www.362tq.com/kashi/7tian.html 推荐查看天气:http://www.362tq.com/kashi/10tian.html 推荐查看天气:http://www.362tq.com/kashi/15tian.html 推荐查看天气:http://www.362tq.com/kashi/40tian.html 推荐查看天气:http://www.362tq.com/shufu/ 推荐查看天气:http://www.362tq.com/shufu/zuotian.html 推荐查看天气:http://www.362tq.com/shufu/7tian.html 推荐查看天气:http://www.362tq.com/shufu/10tian.html 推荐查看天气:http://www.362tq.com/shufu/15tian.html 推荐查看天气:http://www.362tq.com/shufu/40tian.html 推荐查看天气:http://www.362tq.com/shule/ 推荐查看天气:http://www.362tq.com/shule/zuotian.html 推荐查看天气:http://www.362tq.com/shule/7tian.html 推荐查看天气:http://www.362tq.com/shule/10tian.html 推荐查看天气:http://www.362tq.com/shule/15tian.html 推荐查看天气:http://www.362tq.com/shule/40tian.html 推荐查看天气:http://www.362tq.com/yingjisha/ 推荐查看天气:http://www.362tq.com/yingjisha/zuotian.html 推荐查看天气:http://www.362tq.com/yingjisha/7tian.html 推荐查看天气:http://www.362tq.com/yingjisha/10tian.html 推荐查看天气:http://www.362tq.com/yingjisha/15tian.html 推荐查看天气:http://www.362tq.com/yingjisha/40tian.html 推荐查看天气:http://www.362tq.com/zepu/ 推荐查看天气:http://www.362tq.com/zepu/zuotian.html 推荐查看天气:http://www.362tq.com/zepu/7tian.html 推荐查看天气:http://www.362tq.com/zepu/10tian.html 推荐查看天气:http://www.362tq.com/zepu/15tian.html 推荐查看天气:http://www.362tq.com/zepu/40tian.html 推荐查看天气:http://www.362tq.com/shache/ 推荐查看天气:http://www.362tq.com/shache/zuotian.html 推荐查看天气:http://www.362tq.com/shache/7tian.html 推荐查看天气:http://www.362tq.com/shache/10tian.html 推荐查看天气:http://www.362tq.com/shache/15tian.html 推荐查看天气:http://www.362tq.com/shache/40tian.html 推荐查看天气:http://www.362tq.com/yecheng/ 推荐查看天气:http://www.362tq.com/yecheng/zuotian.html 推荐查看天气:http://www.362tq.com/yecheng/7tian.html 推荐查看天气:http://www.362tq.com/yecheng/10tian.html 推荐查看天气:http://www.362tq.com/yecheng/15tian.html 推荐查看天气:http://www.362tq.com/yecheng/40tian.html 推荐查看天气:http://www.362tq.com/maigaiti/ 推荐查看天气:http://www.362tq.com/maigaiti/zuotian.html 推荐查看天气:http://www.362tq.com/maigaiti/7tian.html 推荐查看天气:http://www.362tq.com/maigaiti/10tian.html 推荐查看天气:http://www.362tq.com/maigaiti/15tian.html 推荐查看天气:http://www.362tq.com/maigaiti/40tian.html 推荐查看天气:http://www.362tq.com/yuepuhu/ 推荐查看天气:http://www.362tq.com/yuepuhu/zuotian.html 推荐查看天气:http://www.362tq.com/yuepuhu/7tian.html 推荐查看天气:http://www.362tq.com/yuepuhu/10tian.html 推荐查看天气:http://www.362tq.com/yuepuhu/15tian.html 推荐查看天气:http://www.362tq.com/yuepuhu/40tian.html 推荐查看天气:http://www.362tq.com/jiashi/ 推荐查看天气:http://www.362tq.com/jiashi/zuotian.html 推荐查看天气:http://www.362tq.com/jiashi/7tian.html 推荐查看天气:http://www.362tq.com/jiashi/10tian.html 推荐查看天气:http://www.362tq.com/jiashi/15tian.html 推荐查看天气:http://www.362tq.com/jiashi/40tian.html 推荐查看天气:http://www.362tq.com/bachu/ 推荐查看天气:http://www.362tq.com/bachu/zuotian.html 推荐查看天气:http://www.362tq.com/bachu/7tian.html 推荐查看天气:http://www.362tq.com/bachu/10tian.html 推荐查看天气:http://www.362tq.com/bachu/15tian.html 推荐查看天气:http://www.362tq.com/bachu/40tian.html 推荐查看天气:http://www.362tq.com/tashikuergan/ 推荐查看天气:http://www.362tq.com/tashikuergan/zuotian.html 推荐查看天气:http://www.362tq.com/tashikuergan/7tian.html 推荐查看天气:http://www.362tq.com/tashikuergan/10tian.html 推荐查看天气:http://www.362tq.com/tashikuergan/15tian.html 推荐查看天气:http://www.362tq.com/tashikuergan/40tian.html 推荐查看天气:http://www.362tq.com/hetian/ 推荐查看天气:http://www.362tq.com/hetian/zuotian.html 推荐查看天气:http://www.362tq.com/hetian/7tian.html 推荐查看天气:http://www.362tq.com/hetian/10tian.html 推荐查看天气:http://www.362tq.com/hetian/15tian.html 推荐查看天气:http://www.362tq.com/hetian/40tian.html 推荐查看天气:http://www.362tq.com/moyu/ 推荐查看天气:http://www.362tq.com/moyu/zuotian.html 推荐查看天气:http://www.362tq.com/moyu/7tian.html 推荐查看天气:http://www.362tq.com/moyu/10tian.html 推荐查看天气:http://www.362tq.com/moyu/15tian.html 推荐查看天气:http://www.362tq.com/moyu/40tian.html 推荐查看天气:http://www.362tq.com/pishan/ 推荐查看天气:http://www.362tq.com/pishan/zuotian.html 推荐查看天气:http://www.362tq.com/pishan/7tian.html 推荐查看天气:http://www.362tq.com/pishan/10tian.html 推荐查看天气:http://www.362tq.com/pishan/15tian.html 推荐查看天气:http://www.362tq.com/pishan/40tian.html 推荐查看天气:http://www.362tq.com/luopu/ 推荐查看天气:http://www.362tq.com/luopu/zuotian.html 推荐查看天气:http://www.362tq.com/luopu/7tian.html 推荐查看天气:http://www.362tq.com/luopu/10tian.html 推荐查看天气:http://www.362tq.com/luopu/15tian.html 推荐查看天气:http://www.362tq.com/luopu/40tian.html 推荐查看天气:http://www.362tq.com/cele/ 推荐查看天气:http://www.362tq.com/cele/zuotian.html 推荐查看天气:http://www.362tq.com/cele/7tian.html 推荐查看天气:http://www.362tq.com/cele/10tian.html 推荐查看天气:http://www.362tq.com/cele/15tian.html 推荐查看天气:http://www.362tq.com/cele/40tian.html 推荐查看天气:http://www.362tq.com/yutian/ 推荐查看天气:http://www.362tq.com/yutian/zuotian.html 推荐查看天气:http://www.362tq.com/yutian/7tian.html 推荐查看天气:http://www.362tq.com/yutian/10tian.html 推荐查看天气:http://www.362tq.com/yutian/15tian.html 推荐查看天气:http://www.362tq.com/yutian/40tian.html 推荐查看天气:http://www.362tq.com/minfeng/

优秀的个人博客,低调大师

JavaScript 可选链 ?. 的五种误用场景与替代写法

可选链操作符 `?.` 从 ES2020 正式进入标准,现在已经是日常开发里离不开的语法。它让深层属性访问变得安全,也让很多原本需要临时变量判断的代码缩短到一行。但我在维护团队代码和 review 时发现,可选链被拿来当“万能防错”的情况越来越多:有人用它包住函数调用,有人用它做条件分支,有人把整个对象链都打上问号,结果运行时该抛的错误不抛了,该处理的空值被静默跳过,调试时反而更难定位问题。可选链本质上只做一件事——当左侧为 `null` 或 `undefined` 时短路求值,它不是类型守卫,也不是错误捕获机制。这篇文章结合真实代码片段,梳理几个常见的误用场景,并给出更清晰的替代写法。 ## 用 `?.` 包住函数调用,吞掉了参数错误 见过这样的代码: ```js function renderUser(user) { return user?.getProfile?.().name; } ``` 调用方传了一个完整对象,但 `getProfile` 因为重构被删掉了,于是 `user?.getProfile?.()` 返回 `undefined`,接着 `.name` 直接抛出 `Cannot read properties of undefined`。可选链把“方法不存在”这个本应尽早暴露的问题推迟到了属性访问阶段,错误信息变得莫名其妙。 如果 `getProfile` 是接口约定必须存在的方法,就不该用 `?.`: ```js function renderUser(user) { if (!user || typeof user.getProfile !== 'function') { throw new TypeError('renderUser 需要一个带 getProfile 方法的用户对象'); } return user.getProfile().name; } ``` 可选链适合处理“数据可能不存在”的领域,比如后端返回的可选字段,而不是用来掩盖调用约定被破坏的事实。 ## 把 `?.` 当成条件判断的替代品 ```js if (config?.features?.darkMode) { enableDarkMode(); } ``` 这段代码能跑,但表达的意思很含糊:`config` 不存在、`features` 不存在、`darkMode` 为 `false`,三种情况走同一个分支。如果业务上需要区分“配置没加载”和“用户没开暗色模式”,这种写法会丢掉信息。 更麻烦的是当这个值需要参与逻辑运算时: ```js const isDark = config?.features?.darkMode || false; ``` 如果 `darkMode` 是 `0` 或空字符串,`||` 会把它们也转成 `false`,而 `??` 才能正确保留 falsy 值: ```js const isDark = config?.features?.darkMode ?? false; ``` 可选链和 `??` 经常一起出现,但它们的短路逻辑不同。`?.` 只在 `null`/`undefined` 时短路,`||` 会对所有 falsy 值生效,混用之前先想清楚字段的取值范围。 ## 可选链不能阻止对 `null` 继续取值 ```js const city = order?.address?.city?.toUpperCase(); ``` 如果 `city` 存在但是数字类型,`.toUpperCase` 会直接报错。可选链只检查左侧是不是 `null` 或 `undefined`,不检查类型。这类代码在 TypeScript 里如果开启了严格模式,通常会被类型检查拦住,但在 JS 项目里很容易漏过去。 替代方式是把类型约束交给 TS,或者显式判断: ```ts type City = string | undefined; function formatCity(city: City): string { return typeof city === 'string' ? city.toUpperCase() : ''; } ``` 用 `?.` 做字符串方法调用时,先确认字段的类型定义,而不是靠运行时侥幸。 ## 在赋值左侧使用 `?.` 是语法错误 ```js user?.name = 'Alice'; // SyntaxError ``` 可选链不能作为赋值目标,这一点在写更新逻辑时容易踩到。有人想表达“如果 user 存在就更新”,正确的写法是: ```js if (user) { user.name = 'Alice'; } ``` 或者用可选链读取,再用独立赋值: ```js const target = user?.profile; if (target) { target.name = 'Alice'; } ``` 同样,`delete user?.name` 也是不允许的。可选链的设计目标是安全读取,不是安全写入。 ## 深层可选链掩盖了数据结构问题 ```js const value = a?.b?.c?.d?.e; ``` 五个问号连在一起,通常意味着数据结构不稳定,或者调用方不确定自己在处理什么。这种代码短期能避免报错,长期会让空值来源无法追溯。更好的做法是在边界层做数据校验,把不确定的结构转换成确定的内部模型: ```js function normalizeResponse(raw) { return { user: { name: raw?.user?.name ?? '匿名', avatar: raw?.user?.avatar ?? DEFAULT_AVATAR, }, }; } ``` 这样深层可选链只出现在一个地方,业务代码拿到的是已经规整过的对象,后续访问不需要再层层打问号。可选链是边界处理的工具,不是内部数据流的常态。 ## 和 `try/catch` 的取舍 有人用可选链替代 `try/catch` 来防御 `JSON.parse`: ```js const data = JSON.parse(input)?.payload; ``` 这完全无效,因为 `JSON.parse` 解析失败会直接抛错,可选链不会拦截。正确做法还是包裹 try/catch: ```js function parsePayload(input) { try { return JSON.parse(input).payload; } catch { return null; } } ``` 可选链处理的是属性访问路径上的 `null`/`undefined`,异常控制流是另一套机制。把两者混在一起,只会让错误处理变得模糊。 可选链本身很好用,但每加一个 `?` 之前,问一下自己:这里真的是“可能不存在”,还是“我不确定它存不存在”?前者是合理的边界处理,后者需要去补类型定义或数据校验。 推荐查看天气:https://www.0dtq.com/wuzhi/15tian.html 推荐查看天气:https://www.0dtq.com/wuzhi/40tian.html 推荐查看天气:https://www.0dtq.com/jiaozuowenxian/ 推荐查看天气:https://www.0dtq.com/jiaozuowenxian/zuotian.html 推荐查看天气:https://www.0dtq.com/jiaozuowenxian/7tian.html 推荐查看天气:https://www.0dtq.com/jiaozuowenxian/10tian.html 推荐查看天气:https://www.0dtq.com/jiaozuowenxian/15tian.html 推荐查看天气:https://www.0dtq.com/jiaozuowenxian/40tian.html 推荐查看天气:https://www.0dtq.com/qinyang/ 推荐查看天气:https://www.0dtq.com/qinyang/zuotian.html 推荐查看天气:https://www.0dtq.com/qinyang/7tian.html 推荐查看天气:https://www.0dtq.com/qinyang/10tian.html 推荐查看天气:https://www.0dtq.com/qinyang/15tian.html 推荐查看天气:https://www.0dtq.com/qinyang/40tian.html 推荐查看天气:https://www.0dtq.com/mengzhou/ 推荐查看天气:https://www.0dtq.com/mengzhou/zuotian.html 推荐查看天气:https://www.0dtq.com/mengzhou/7tian.html 推荐查看天气:https://www.0dtq.com/mengzhou/10tian.html 推荐查看天气:https://www.0dtq.com/mengzhou/15tian.html 推荐查看天气:https://www.0dtq.com/mengzhou/40tian.html 推荐查看天气:https://www.0dtq.com/jiyuan/ 推荐查看天气:https://www.0dtq.com/jiyuan/zuotian.html 推荐查看天气:https://www.0dtq.com/jiyuan/7tian.html 推荐查看天气:https://www.0dtq.com/jiyuan/10tian.html 推荐查看天气:https://www.0dtq.com/jiyuan/15tian.html 推荐查看天气:https://www.0dtq.com/jiyuan/40tian.html 推荐查看天气:https://www.0dtq.com/puyang/ 推荐查看天气:https://www.0dtq.com/puyang/zuotian.html 推荐查看天气:https://www.0dtq.com/puyang/7tian.html 推荐查看天气:https://www.0dtq.com/puyang/10tian.html 推荐查看天气:https://www.0dtq.com/puyang/15tian.html 推荐查看天气:https://www.0dtq.com/puyang/40tian.html 推荐查看天气:https://www.0dtq.com/qingfeng/ 推荐查看天气:https://www.0dtq.com/qingfeng/zuotian.html 推荐查看天气:https://www.0dtq.com/qingfeng/7tian.html 推荐查看天气:https://www.0dtq.com/qingfeng/10tian.html 推荐查看天气:https://www.0dtq.com/qingfeng/15tian.html 推荐查看天气:https://www.0dtq.com/qingfeng/40tian.html 推荐查看天气:https://www.0dtq.com/nanle/ 推荐查看天气:https://www.0dtq.com/nanle/zuotian.html 推荐查看天气:https://www.0dtq.com/nanle/7tian.html 推荐查看天气:https://www.0dtq.com/nanle/10tian.html 推荐查看天气:https://www.0dtq.com/nanle/15tian.html 推荐查看天气:https://www.0dtq.com/nanle/40tian.html 推荐查看天气:https://www.0dtq.com/fanxian/ 推荐查看天气:https://www.0dtq.com/fanxian/zuotian.html 推荐查看天气:https://www.0dtq.com/fanxian/7tian.html 推荐查看天气:https://www.0dtq.com/fanxian/10tian.html 推荐查看天气:https://www.0dtq.com/fanxian/15tian.html 推荐查看天气:https://www.0dtq.com/fanxian/40tian.html 推荐查看天气:https://www.0dtq.com/taiqian/ 推荐查看天气:https://www.0dtq.com/taiqian/zuotian.html 推荐查看天气:https://www.0dtq.com/taiqian/7tian.html 推荐查看天气:https://www.0dtq.com/taiqian/10tian.html 推荐查看天气:https://www.0dtq.com/taiqian/15tian.html 推荐查看天气:https://www.0dtq.com/taiqian/40tian.html 推荐查看天气:https://www.0dtq.com/xuchang/ 推荐查看天气:https://www.0dtq.com/xuchang/zuotian.html 推荐查看天气:https://www.0dtq.com/xuchang/7tian.html 推荐查看天气:https://www.0dtq.com/xuchang/10tian.html 推荐查看天气:https://www.0dtq.com/xuchang/15tian.html 推荐查看天气:https://www.0dtq.com/xuchang/40tian.html 推荐查看天气:https://www.0dtq.com/xuchangyanling/ 推荐查看天气:https://www.0dtq.com/xuchangyanling/zuotian.html 推荐查看天气:https://www.0dtq.com/xuchangyanling/7tian.html 推荐查看天气:https://www.0dtq.com/xuchangyanling/10tian.html 推荐查看天气:https://www.0dtq.com/xuchangyanling/15tian.html 推荐查看天气:https://www.0dtq.com/xuchangyanling/40tian.html 推荐查看天气:https://www.0dtq.com/xuchangxiangcheng/ 推荐查看天气:https://www.0dtq.com/xuchangxiangcheng/zuotian.html 推荐查看天气:https://www.0dtq.com/xuchangxiangcheng/7tian.html 推荐查看天气:https://www.0dtq.com/xuchangxiangcheng/10tian.html 推荐查看天气:https://www.0dtq.com/xuchangxiangcheng/15tian.html 推荐查看天气:https://www.0dtq.com/xuchangxiangcheng/40tian.html 推荐查看天气:https://www.0dtq.com/xuchangyuzhou/ 推荐查看天气:https://www.0dtq.com/xuchangyuzhou/zuotian.html 推荐查看天气:https://www.0dtq.com/xuchangyuzhou/7tian.html 推荐查看天气:https://www.0dtq.com/xuchangyuzhou/10tian.html 推荐查看天气:https://www.0dtq.com/xuchangyuzhou/15tian.html 推荐查看天气:https://www.0dtq.com/xuchangyuzhou/40tian.html 推荐查看天气:https://www.0dtq.com/changge/ 推荐查看天气:https://www.0dtq.com/changge/zuotian.html 推荐查看天气:https://www.0dtq.com/changge/7tian.html 推荐查看天气:https://www.0dtq.com/changge/10tian.html 推荐查看天气:https://www.0dtq.com/changge/15tian.html 推荐查看天气:https://www.0dtq.com/changge/40tian.html 推荐查看天气:https://www.0dtq.com/luohe/ 推荐查看天气:https://www.0dtq.com/luohe/zuotian.html 推荐查看天气:https://www.0dtq.com/luohe/7tian.html 推荐查看天气:https://www.0dtq.com/luohe/10tian.html 推荐查看天气:https://www.0dtq.com/luohe/15tian.html 推荐查看天气:https://www.0dtq.com/luohe/40tian.html 推荐查看天气:https://www.0dtq.com/yuanhui/ 推荐查看天气:https://www.0dtq.com/yuanhui/zuotian.html 推荐查看天气:https://www.0dtq.com/yuanhui/7tian.html 推荐查看天气:https://www.0dtq.com/yuanhui/10tian.html 推荐查看天气:https://www.0dtq.com/yuanhui/15tian.html 推荐查看天气:https://www.0dtq.com/yuanhui/40tian.html 推荐查看天气:https://www.0dtq.com/wuyang/ 推荐查看天气:https://www.0dtq.com/wuyang/zuotian.html 推荐查看天气:https://www.0dtq.com/wuyang/7tian.html 推荐查看天气:https://www.0dtq.com/wuyang/10tian.html 推荐查看天气:https://www.0dtq.com/wuyang/15tian.html 推荐查看天气:https://www.0dtq.com/wuyang/40tian.html 推荐查看天气:https://www.0dtq.com/linying/ 推荐查看天气:https://www.0dtq.com/linying/zuotian.html 推荐查看天气:https://www.0dtq.com/linying/7tian.html 推荐查看天气:https://www.0dtq.com/linying/10tian.html 推荐查看天气:https://www.0dtq.com/linying/15tian.html 推荐查看天气:https://www.0dtq.com/linying/40tian.html 推荐查看天气:https://www.0dtq.com/sanmenxia/ 推荐查看天气:https://www.0dtq.com/sanmenxia/zuotian.html 推荐查看天气:https://www.0dtq.com/sanmenxia/7tian.html 推荐查看天气:https://www.0dtq.com/sanmenxia/10tian.html 推荐查看天气:https://www.0dtq.com/sanmenxia/15tian.html 推荐查看天气:https://www.0dtq.com/sanmenxia/40tian.html 推荐查看天气:https://www.0dtq.com/hubin/ 推荐查看天气:https://www.0dtq.com/hubin/zuotian.html 推荐查看天气:https://www.0dtq.com/hubin/7tian.html 推荐查看天气:https://www.0dtq.com/hubin/10tian.html 推荐查看天气:https://www.0dtq.com/hubin/15tian.html 推荐查看天气:https://www.0dtq.com/hubin/40tian.html 推荐查看天气:https://www.0dtq.com/shengchi/ 推荐查看天气:https://www.0dtq.com/shengchi/zuotian.html 推荐查看天气:https://www.0dtq.com/shengchi/7tian.html 推荐查看天气:https://www.0dtq.com/shengchi/10tian.html 推荐查看天气:https://www.0dtq.com/shengchi/15tian.html 推荐查看天气:https://www.0dtq.com/shengchi/40tian.html 推荐查看天气:https://www.0dtq.com/shanxian/ 推荐查看天气:https://www.0dtq.com/shanxian/zuotian.html 推荐查看天气:https://www.0dtq.com/shanxian/7tian.html 推荐查看天气:https://www.0dtq.com/shanxian/10tian.html 推荐查看天气:https://www.0dtq.com/shanxian/15tian.html 推荐查看天气:https://www.0dtq.com/shanxian/40tian.html 推荐查看天气:https://www.0dtq.com/lushi/ 推荐查看天气:https://www.0dtq.com/lushi/zuotian.html 推荐查看天气:https://www.0dtq.com/lushi/7tian.html 推荐查看天气:https://www.0dtq.com/lushi/10tian.html 推荐查看天气:https://www.0dtq.com/lushi/15tian.html 推荐查看天气:https://www.0dtq.com/lushi/40tian.html 推荐查看天气:https://www.0dtq.com/yima/ 推荐查看天气:https://www.0dtq.com/yima/zuotian.html 推荐查看天气:https://www.0dtq.com/yima/7tian.html 推荐查看天气:https://www.0dtq.com/yima/10tian.html 推荐查看天气:https://www.0dtq.com/yima/15tian.html 推荐查看天气:https://www.0dtq.com/yima/40tian.html 推荐查看天气:https://www.0dtq.com/lingbao/ 推荐查看天气:https://www.0dtq.com/lingbao/zuotian.html 推荐查看天气:https://www.0dtq.com/lingbao/7tian.html 推荐查看天气:https://www.0dtq.com/lingbao/10tian.html 推荐查看天气:https://www.0dtq.com/lingbao/15tian.html 推荐查看天气:https://www.0dtq.com/lingbao/40tian.html 推荐查看天气:https://www.0dtq.com/nanyang/ 推荐查看天气:https://www.0dtq.com/nanyang/zuotian.html 推荐查看天气:https://www.0dtq.com/nanyang/7tian.html 推荐查看天气:https://www.0dtq.com/nanyang/10tian.html 推荐查看天气:https://www.0dtq.com/nanyang/15tian.html 推荐查看天气:https://www.0dtq.com/nanyang/40tian.html 推荐查看天气:https://www.0dtq.com/wancheng/ 推荐查看天气:https://www.0dtq.com/wancheng/zuotian.html 推荐查看天气:https://www.0dtq.com/wancheng/7tian.html 推荐查看天气:https://www.0dtq.com/wancheng/10tian.html 推荐查看天气:https://www.0dtq.com/wancheng/15tian.html 推荐查看天气:https://www.0dtq.com/wancheng/40tian.html 推荐查看天气:https://www.0dtq.com/wolong/ 推荐查看天气:https://www.0dtq.com/wolong/zuotian.html 推荐查看天气:https://www.0dtq.com/wolong/7tian.html 推荐查看天气:https://www.0dtq.com/wolong/10tian.html 推荐查看天气:https://www.0dtq.com/wolong/15tian.html 推荐查看天气:https://www.0dtq.com/wolong/40tian.html 推荐查看天气:https://www.0dtq.com/nanzhao/ 推荐查看天气:https://www.0dtq.com/nanzhao/zuotian.html 推荐查看天气:https://www.0dtq.com/nanzhao/7tian.html 推荐查看天气:https://www.0dtq.com/nanzhao/10tian.html 推荐查看天气:https://www.0dtq.com/nanzhao/15tian.html 推荐查看天气:https://www.0dtq.com/nanzhao/40tian.html 推荐查看天气:https://www.0dtq.com/nanyangfangcheng/ 推荐查看天气:https://www.0dtq.com/nanyangfangcheng/zuotian.html 推荐查看天气:https://www.0dtq.com/nanyangfangcheng/7tian.html 推荐查看天气:https://www.0dtq.com/nanyangfangcheng/10tian.html 推荐查看天气:https://www.0dtq.com/nanyangfangcheng/15tian.html 推荐查看天气:https://www.0dtq.com/nanyangfangcheng/40tian.html 推荐查看天气:https://www.0dtq.com/nanyangxixia/ 推荐查看天气:https://www.0dtq.com/nanyangxixia/zuotian.html 推荐查看天气:https://www.0dtq.com/nanyangxixia/7tian.html 推荐查看天气:https://www.0dtq.com/nanyangxixia/10tian.html 推荐查看天气:https://www.0dtq.com/nanyangxixia/15tian.html 推荐查看天气:https://www.0dtq.com/nanyangxixia/40tian.html 推荐查看天气:https://www.0dtq.com/nanyangzhenping/ 推荐查看天气:https://www.0dtq.com/nanyangzhenping/zuotian.html 推荐查看天气:https://www.0dtq.com/nanyangzhenping/7tian.html 推荐查看天气:https://www.0dtq.com/nanyangzhenping/10tian.html 推荐查看天气:https://www.0dtq.com/nanyangzhenping/15tian.html 推荐查看天气:https://www.0dtq.com/nanyangzhenping/40tian.html 推荐查看天气:https://www.0dtq.com/naxiang/ 推荐查看天气:https://www.0dtq.com/naxiang/zuotian.html 推荐查看天气:https://www.0dtq.com/naxiang/7tian.html 推荐查看天气:https://www.0dtq.com/naxiang/10tian.html 推荐查看天气:https://www.0dtq.com/naxiang/15tian.html 推荐查看天气:https://www.0dtq.com/naxiang/40tian.html

优秀的个人博客,低调大师

JavaScript 中的 Array.prototype.sort 为何不总是按预期排序?

在开发中,我们经常用 `Array.prototype.sort()` 对数组排序,特别是处理数字数组时,默认行为常常让人困惑。比如 `[1, 5, 10, 2].sort()` 会得到 `[1, 10, 2, 5]`,而不是按数值大小排列。这是因为 `sort` 默认将元素转换为字符串,再比较 UTF-16 码元序列。更隐蔽的问题出现在比较函数返回值不规范、数组包含 `undefined` 或稀疏元素,以及现代引擎对稳定排序的差异上。本文从底层规范与常见误区出发,讨论排序不生效的原因、比较函数的正确写法、以及处理数字、对象、多字段排序时的可靠做法,同时涉及性能与稳定性的取舍。 ## 默认比较是字符串比较 `sort()` 不传参数时,会把所有元素转成字符串,然后按 UTF-16 码元顺序比较。数字 `10` 转成 `"10"`,`2` 转成 `"2"`,字符串比较中 `"10"` 的字符 `'1'` 排在 `'2'` 前面,所以 `10` 会出现在 `2` 之前。这个行为从 ES1 就定下来了,不能依赖它做数值排序。 ```js const nums = [1, 5, 10, 2]; nums.sort(); console.log(nums); // [1, 10, 2, 5] ``` 要按数值排序,必须提供比较函数。 ```js nums.sort((a, b) => a - b); console.log(nums); // [1, 2, 5, 10] ``` ## 比较函数返回值的要求 比较函数应该返回一个数字: - 小于 0:`a` 排在 `b` 前面 - 大于 0:`b` 排在 `a` 前面 - 等于 0:保持相对顺序(在稳定排序下) 很多人会写成返回布尔值或者直接返回差值却忽略浮点数精度。例如 `return a > b` 只会返回 `true` 或 `false`,被隐式转换为 `1` 或 `0`,导致 `a a > b); // 结果不可靠 // 正确:返回数值 [3, 1, 2].sort((a, b) => a - b); ``` 对于可能超出安全整数的数字,用 `a - b` 也可能溢出或丢失精度,更安全的是用比较运算符返回 -1 / 0 / 1。 ```js function compareNumbers(a, b) { if (a b) return 1; return 0; } ``` ## undefined、null 和稀疏元素 `undefined` 元素会被 `sort` 一律排到数组末尾,比较函数也不会被调用。`null` 则会被转换成字符串 `"null"`。稀疏数组中的空槽会被当作 `undefined` 处理,并且排序后空槽可能被具体值填充,改变数组长度。 ```js const arr = [3, undefined, 1, null, 2]; arr.sort((a, b) => a - b); console.log(arr); // [1, 2, 3, null, undefined] ``` 如果数据来自 JSON 或接口,字段可能缺失,最好先过滤或映射为统一类型再排序。 ## 对象数组和多字段排序 按对象属性排序时,要确保属性可比较且类型一致。混合字符串和数字时,`a - b` 会得到 `NaN`,比较函数返回 `NaN` 被当作 0,排序失效。 ```js const users = [ { name: 'Alice', age: 30 }, { name: 'Bob', age: 25 }, { name: 'Carol', age: 30 } ]; users.sort((a, b) => a.age - b.age); ``` 多字段排序可以用链式比较,先比较主要字段,相等时再比较次要字段。 ```js users.sort((a, b) => { if (a.age !== b.age) return a.age - b.age; return a.name.localeCompare(b.name); }); ``` `localeCompare` 适合字符串比较,能处理语言敏感的大小写和变音符号。 ## 稳定排序与引擎差异 ES2019 之前,规范不要求 `sort` 稳定,V8 对短数组用插入排序(稳定),长数组用快速排序(不稳定)。ES2019 起要求稳定排序,所有现代引擎都遵守。但稳定只保证比较函数返回 0 的元素相对顺序不变,如果比较函数本身设计有问题,依然会得到意外结果。 ```js const items = [ { id: 1, type: 'b' }, { id: 2, type: 'a' }, { id: 3, type: 'b' } ]; items.sort((a, b) => a.type.localeCompare(b.type)); // id 为 1 和 3 的元素都会保持原有相对顺序 ``` ## 性能与拷贝 `sort` 会直接修改原数组。如果不希望改变原数组,先用 `slice()` 或扩展运算符复制。 ```js const sorted = [...arr].sort((a, b) => a - b); ``` 比较函数应尽量简单,避免在函数内部做复杂计算或频繁访问闭包变量。对于大数组,可以先映射出排序键,排序后再映射回原对象,减少重复属性访问。 ```js const sorted = arr .map(item => ({ item, key: item.value })) .sort((a, b) => a.key - b.key) .map(entry => entry.item); ``` 如果只需要前 N 个元素,不必全量排序,可以用堆或选择算法,但多数场景下 `sort` 足够快。 ## 实际排查建议 遇到排序不符合预期,先检查比较函数返回值是否符合规范,再确认数组元素类型是否一致,有无 `undefined`、`null` 或数字字符串混合。用 `console.log` 在比较函数里打印参数和返回值是快速定位手段,但线上环境记得移除。单元测试里加几条边界用例,比如空数组、单元素、相同值、极端数值,能避免大部分低级错误。 推荐查看天气:https://www.40tianqi.com/jiancaoping/ 推荐查看天气:https://www.40tianqi.com/jiancaoping/zuotian.html 推荐查看天气:https://www.40tianqi.com/jiancaoping/7tian.html 推荐查看天气:https://www.40tianqi.com/jiancaoping/10tian.html 推荐查看天气:https://www.40tianqi.com/jiancaoping/15tian.html 推荐查看天气:https://www.40tianqi.com/jiancaoping/40tian.html 推荐查看天气:https://www.40tianqi.com/wanbailin/ 推荐查看天气:https://www.40tianqi.com/wanbailin/zuotian.html 推荐查看天气:https://www.40tianqi.com/wanbailin/7tian.html 推荐查看天气:https://www.40tianqi.com/wanbailin/10tian.html 推荐查看天气:https://www.40tianqi.com/wanbailin/15tian.html 推荐查看天气:https://www.40tianqi.com/wanbailin/40tian.html 推荐查看天气:https://www.40tianqi.com/jinyuan/ 推荐查看天气:https://www.40tianqi.com/jinyuan/zuotian.html 推荐查看天气:https://www.40tianqi.com/jinyuan/7tian.html 推荐查看天气:https://www.40tianqi.com/jinyuan/10tian.html 推荐查看天气:https://www.40tianqi.com/jinyuan/15tian.html 推荐查看天气:https://www.40tianqi.com/jinyuan/40tian.html 推荐查看天气:https://www.40tianqi.com/qingxu/ 推荐查看天气:https://www.40tianqi.com/qingxu/zuotian.html 推荐查看天气:https://www.40tianqi.com/qingxu/7tian.html 推荐查看天气:https://www.40tianqi.com/qingxu/10tian.html 推荐查看天气:https://www.40tianqi.com/qingxu/15tian.html 推荐查看天气:https://www.40tianqi.com/qingxu/40tian.html 推荐查看天气:https://www.40tianqi.com/yangqu/ 推荐查看天气:https://www.40tianqi.com/yangqu/zuotian.html 推荐查看天气:https://www.40tianqi.com/yangqu/7tian.html 推荐查看天气:https://www.40tianqi.com/yangqu/10tian.html 推荐查看天气:https://www.40tianqi.com/yangqu/15tian.html 推荐查看天气:https://www.40tianqi.com/yangqu/40tian.html 推荐查看天气:https://www.40tianqi.com/loufan/ 推荐查看天气:https://www.40tianqi.com/loufan/zuotian.html 推荐查看天气:https://www.40tianqi.com/loufan/7tian.html 推荐查看天气:https://www.40tianqi.com/loufan/10tian.html 推荐查看天气:https://www.40tianqi.com/loufan/15tian.html 推荐查看天气:https://www.40tianqi.com/loufan/40tian.html 推荐查看天气:https://www.40tianqi.com/gujiao/ 推荐查看天气:https://www.40tianqi.com/gujiao/zuotian.html 推荐查看天气:https://www.40tianqi.com/gujiao/7tian.html 推荐查看天气:https://www.40tianqi.com/gujiao/10tian.html 推荐查看天气:https://www.40tianqi.com/gujiao/15tian.html 推荐查看天气:https://www.40tianqi.com/gujiao/40tian.html 推荐查看天气:https://www.40tianqi.com/datongshi/ 推荐查看天气:https://www.40tianqi.com/datongshi/zuotian.html 推荐查看天气:https://www.40tianqi.com/datongshi/7tian.html 推荐查看天气:https://www.40tianqi.com/datongshi/10tian.html 推荐查看天气:https://www.40tianqi.com/datongshi/15tian.html 推荐查看天气:https://www.40tianqi.com/datongshi/40tian.html 推荐查看天气:https://www.40tianqi.com/nanjiao/ 推荐查看天气:https://www.40tianqi.com/nanjiao/zuotian.html 推荐查看天气:https://www.40tianqi.com/nanjiao/7tian.html 推荐查看天气:https://www.40tianqi.com/nanjiao/10tian.html 推荐查看天气:https://www.40tianqi.com/nanjiao/15tian.html 推荐查看天气:https://www.40tianqi.com/nanjiao/40tian.html 推荐查看天气:https://www.40tianqi.com/xinrong/ 推荐查看天气:https://www.40tianqi.com/xinrong/zuotian.html 推荐查看天气:https://www.40tianqi.com/xinrong/7tian.html 推荐查看天气:https://www.40tianqi.com/xinrong/10tian.html 推荐查看天气:https://www.40tianqi.com/xinrong/15tian.html 推荐查看天气:https://www.40tianqi.com/xinrong/40tian.html 推荐查看天气:https://www.40tianqi.com/yanggao/ 推荐查看天气:https://www.40tianqi.com/yanggao/zuotian.html 推荐查看天气:https://www.40tianqi.com/yanggao/7tian.html 推荐查看天气:https://www.40tianqi.com/yanggao/10tian.html 推荐查看天气:https://www.40tianqi.com/yanggao/15tian.html 推荐查看天气:https://www.40tianqi.com/yanggao/40tian.html 推荐查看天气:https://www.40tianqi.com/tianzhen/ 推荐查看天气:https://www.40tianqi.com/tianzhen/zuotian.html 推荐查看天气:https://www.40tianqi.com/tianzhen/7tian.html 推荐查看天气:https://www.40tianqi.com/tianzhen/10tian.html 推荐查看天气:https://www.40tianqi.com/tianzhen/15tian.html 推荐查看天气:https://www.40tianqi.com/tianzhen/40tian.html 推荐查看天气:https://www.40tianqi.com/datongguangling/ 推荐查看天气:https://www.40tianqi.com/datongguangling/zuotian.html 推荐查看天气:https://www.40tianqi.com/datongguangling/7tian.html 推荐查看天气:https://www.40tianqi.com/datongguangling/10tian.html 推荐查看天气:https://www.40tianqi.com/datongguangling/15tian.html 推荐查看天气:https://www.40tianqi.com/datongguangling/40tian.html 推荐查看天气:https://www.40tianqi.com/lingqiu/ 推荐查看天气:https://www.40tianqi.com/lingqiu/zuotian.html 推荐查看天气:https://www.40tianqi.com/lingqiu/7tian.html 推荐查看天气:https://www.40tianqi.com/lingqiu/10tian.html 推荐查看天气:https://www.40tianqi.com/lingqiu/15tian.html 推荐查看天气:https://www.40tianqi.com/lingqiu/40tian.html 推荐查看天气:https://www.40tianqi.com/hunyuan/ 推荐查看天气:https://www.40tianqi.com/hunyuan/zuotian.html 推荐查看天气:https://www.40tianqi.com/hunyuan/7tian.html 推荐查看天气:https://www.40tianqi.com/hunyuan/10tian.html 推荐查看天气:https://www.40tianqi.com/hunyuan/15tian.html 推荐查看天气:https://www.40tianqi.com/hunyuan/40tian.html 推荐查看天气:https://www.40tianqi.com/zuoyun/ 推荐查看天气:https://www.40tianqi.com/zuoyun/zuotian.html 推荐查看天气:https://www.40tianqi.com/zuoyun/7tian.html 推荐查看天气:https://www.40tianqi.com/zuoyun/10tian.html 推荐查看天气:https://www.40tianqi.com/zuoyun/15tian.html 推荐查看天气:https://www.40tianqi.com/zuoyun/40tian.html 推荐查看天气:https://www.40tianqi.com/datongxian/ 推荐查看天气:https://www.40tianqi.com/datongxian/zuotian.html 推荐查看天气:https://www.40tianqi.com/datongxian/7tian.html 推荐查看天气:https://www.40tianqi.com/datongxian/10tian.html 推荐查看天气:https://www.40tianqi.com/datongxian/15tian.html 推荐查看天气:https://www.40tianqi.com/datongxian/40tian.html 推荐查看天气:https://www.40tianqi.com/yangquan/ 推荐查看天气:https://www.40tianqi.com/yangquan/zuotian.html 推荐查看天气:https://www.40tianqi.com/yangquan/7tian.html 推荐查看天气:https://www.40tianqi.com/yangquan/10tian.html 推荐查看天气:https://www.40tianqi.com/yangquan/15tian.html 推荐查看天气:https://www.40tianqi.com/yangquan/40tian.html 推荐查看天气:https://www.40tianqi.com/kuangqu/ 推荐查看天气:https://www.40tianqi.com/kuangqu/zuotian.html 推荐查看天气:https://www.40tianqi.com/kuangqu/7tian.html 推荐查看天气:https://www.40tianqi.com/kuangqu/10tian.html 推荐查看天气:https://www.40tianqi.com/kuangqu/15tian.html 推荐查看天气:https://www.40tianqi.com/kuangqu/40tian.html 推荐查看天气:https://www.40tianqi.com/pingding/ 推荐查看天气:https://www.40tianqi.com/pingding/zuotian.html 推荐查看天气:https://www.40tianqi.com/pingding/7tian.html 推荐查看天气:https://www.40tianqi.com/pingding/10tian.html 推荐查看天气:https://www.40tianqi.com/pingding/15tian.html 推荐查看天气:https://www.40tianqi.com/pingding/40tian.html 推荐查看天气:https://www.40tianqi.com/yuxian/ 推荐查看天气:https://www.40tianqi.com/yuxian/zuotian.html 推荐查看天气:https://www.40tianqi.com/yuxian/7tian.html 推荐查看天气:https://www.40tianqi.com/yuxian/10tian.html 推荐查看天气:https://www.40tianqi.com/yuxian/15tian.html 推荐查看天气:https://www.40tianqi.com/yuxian/40tian.html 推荐查看天气:https://www.40tianqi.com/changzhi/ 推荐查看天气:https://www.40tianqi.com/changzhi/zuotian.html 推荐查看天气:https://www.40tianqi.com/changzhi/7tian.html 推荐查看天气:https://www.40tianqi.com/changzhi/10tian.html 推荐查看天气:https://www.40tianqi.com/changzhi/15tian.html 推荐查看天气:https://www.40tianqi.com/changzhi/40tian.html 推荐查看天气:https://www.40tianqi.com/xiangyuan/ 推荐查看天气:https://www.40tianqi.com/xiangyuan/zuotian.html 推荐查看天气:https://www.40tianqi.com/xiangyuan/7tian.html 推荐查看天气:https://www.40tianqi.com/xiangyuan/10tian.html 推荐查看天气:https://www.40tianqi.com/xiangyuan/15tian.html 推荐查看天气:https://www.40tianqi.com/xiangyuan/40tian.html 推荐查看天气:https://www.40tianqi.com/tunliu/ 推荐查看天气:https://www.40tianqi.com/tunliu/zuotian.html 推荐查看天气:https://www.40tianqi.com/tunliu/7tian.html 推荐查看天气:https://www.40tianqi.com/tunliu/10tian.html 推荐查看天气:https://www.40tianqi.com/tunliu/15tian.html 推荐查看天气:https://www.40tianqi.com/tunliu/40tian.html 推荐查看天气:https://www.40tianqi.com/pingshun/ 推荐查看天气:https://www.40tianqi.com/pingshun/zuotian.html 推荐查看天气:https://www.40tianqi.com/pingshun/7tian.html 推荐查看天气:https://www.40tianqi.com/pingshun/10tian.html 推荐查看天气:https://www.40tianqi.com/pingshun/15tian.html 推荐查看天气:https://www.40tianqi.com/pingshun/40tian.html 推荐查看天气:https://www.40tianqi.com/changzhilicheng/ 推荐查看天气:https://www.40tianqi.com/changzhilicheng/zuotian.html 推荐查看天气:https://www.40tianqi.com/changzhilicheng/7tian.html 推荐查看天气:https://www.40tianqi.com/changzhilicheng/10tian.html 推荐查看天气:https://www.40tianqi.com/changzhilicheng/15tian.html 推荐查看天气:https://www.40tianqi.com/changzhilicheng/40tian.html 推荐查看天气:https://www.40tianqi.com/huguan/ 推荐查看天气:https://www.40tianqi.com/huguan/zuotian.html 推荐查看天气:https://www.40tianqi.com/huguan/7tian.html 推荐查看天气:https://www.40tianqi.com/huguan/10tian.html 推荐查看天气:https://www.40tianqi.com/huguan/15tian.html 推荐查看天气:https://www.40tianqi.com/huguan/40tian.html 推荐查看天气:https://www.40tianqi.com/changzi/ 推荐查看天气:https://www.40tianqi.com/changzi/zuotian.html 推荐查看天气:https://www.40tianqi.com/changzi/7tian.html 推荐查看天气:https://www.40tianqi.com/changzi/10tian.html 推荐查看天气:https://www.40tianqi.com/changzi/15tian.html 推荐查看天气:https://www.40tianqi.com/changzi/40tian.html 推荐查看天气:https://www.40tianqi.com/wuxiang/ 推荐查看天气:https://www.40tianqi.com/wuxiang/zuotian.html 推荐查看天气:https://www.40tianqi.com/wuxiang/7tian.html 推荐查看天气:https://www.40tianqi.com/wuxiang/10tian.html 推荐查看天气:https://www.40tianqi.com/wuxiang/15tian.html 推荐查看天气:https://www.40tianqi.com/wuxiang/40tian.html 推荐查看天气:https://www.40tianqi.com/qinxian/ 推荐查看天气:https://www.40tianqi.com/qinxian/zuotian.html 推荐查看天气:https://www.40tianqi.com/qinxian/7tian.html 推荐查看天气:https://www.40tianqi.com/qinxian/10tian.html 推荐查看天气:https://www.40tianqi.com/qinxian/15tian.html 推荐查看天气:https://www.40tianqi.com/qinxian/40tian.html 推荐查看天气:https://www.40tianqi.com/qinyuan/ 推荐查看天气:https://www.40tianqi.com/qinyuan/zuotian.html 推荐查看天气:https://www.40tianqi.com/qinyuan/7tian.html 推荐查看天气:https://www.40tianqi.com/qinyuan/10tian.html 推荐查看天气:https://www.40tianqi.com/qinyuan/15tian.html 推荐查看天气:https://www.40tianqi.com/qinyuan/40tian.html 推荐查看天气:https://www.40tianqi.com/shuozhou/ 推荐查看天气:https://www.40tianqi.com/shuozhou/zuotian.html 推荐查看天气:https://www.40tianqi.com/shuozhou/7tian.html 推荐查看天气:https://www.40tianqi.com/shuozhou/10tian.html 推荐查看天气:https://www.40tianqi.com/shuozhou/15tian.html 推荐查看天气:https://www.40tianqi.com/shuozhou/40tian.html 推荐查看天气:https://www.40tianqi.com/shuocheng/ 推荐查看天气:https://www.40tianqi.com/shuocheng/zuotian.html 推荐查看天气:https://www.40tianqi.com/shuocheng/7tian.html 推荐查看天气:https://www.40tianqi.com/shuocheng/10tian.html 推荐查看天气:https://www.40tianqi.com/shuocheng/15tian.html 推荐查看天气:https://www.40tianqi.com/shuocheng/40tian.html 推荐查看天气:https://www.40tianqi.com/shuozhoupinglu/ 推荐查看天气:https://www.40tianqi.com/shuozhoupinglu/zuotian.html

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册