什么网站可以做海报seo网站推广主要目的不包括
2026/6/21 4:23:18 网站建设 项目流程
什么网站可以做海报,seo网站推广主要目的不包括,在线建站平台免费建网站,最便宜做网站一、Set: 数组去重 快速查找#xff0c;比 filter 快3倍 提到数组去重#xff0c;很多第一反应是 filter indexOf#xff0c;但是这种写法的时间复杂度是O(n)#xff0c;而 Set 天生支持 “唯一值”#xff0c;查找速度是 O(1)#xff0c;还能直接转数组。 示例…一、Set: 数组去重 快速查找比 filter 快3倍提到数组去重很多第一反应是 filter indexOf但是这种写法的时间复杂度是O(n²)而 Set 天生支持 “唯一值”查找速度是 O(1)还能直接转数组。示例用户 ID 去重// 后端返回的重复用户ID列表constduplicateIds[101,102,102,103,103,103];// 1行去重constuniqueIds[...newSet(duplicateIds)];console.log(uniqueIds);// [101, 102, 103]避免重复绑定事件constlistenedEventsnewSet();functionsafeAddEvent(eventName,handler){if(!listenedEvents.has(eventName)){window.addEventListener(eventName,handler);listenedEvents.add(eventName);// 标记已绑定}}// 调用2次也只会绑定1次 scroll 事件safeAddEvent(scroll,()console.log(滚动了));safeAddEvent(scroll,()console.log(滚动了));二、Object.entries() Object.fromEntries()对象数组互转神器以前想遍历对象要用 for…in 循环外加判断 hasOwnProperty如果想把数组转成对象只能手动写循环。这对组合直接一键搞定。示例对象转数组 Object.entries()Object.entries(obj) 会将对象的可枚举键值对转换为一个二维数组格式为 [[key1, value1], [key2, value2], …]。// 原始对象constobj{name:张三,age:20,gender:男};// 对象转数组Object.entries()constarrObject.entries(obj);console.log(arr);// 输出[ [name, 张三], [age, 20], [gender, 男] ]特点只处理对象自身的可枚举属性不包含继承的属性如 toString。数组元素是 [键, 值] 的结构键的类型为字符串即使原对象键是数字也会转为字符串。数组转对象Object.fromEntries(arr) 会将一个二维数组格式为 [[key1, value1], [key2, value2], …]转换为对应的对象数组中的每个子数组的第一个元素作为对象的键第二个元素作为值。// 原始数组格式必须是 [[key, value], ...]constarr[[name,李四],[age,25],[gender,女]];// 数组转对象Object.fromEntries()constobjObject.fromEntries(arr);console.log(obj);// 输出{ name: 李四, age: 25, gender: 女 }注意数组的子数组必须包含至少两个元素否则键对应的值为 undefined。若数组中存在重复的键后面的键值对会覆盖前面的对象键具有唯一性。示例 2修改对象的键或值constobj{name:张三,age:20};// 1. 转数组后修改键名和值constmodifiedArrObject.entries(obj).map(([key,value]){if(keyname)return[username,value];// 改键名if(keyage)return[key,value1];//改值return[key,value];});// modifiedArr: [ [username, 张三], [age, 21] ]// 2. 转回对象constnewObjObject.fromEntries(modifiedArr);console.log(newObj);// { username: 张三, age: 21 }筛选对象属性过滤掉空值// 后端返回的用户信息包含空值字段constuserInfo{name:张三,age:28,avatar:,// 空值需要过滤phone:13800138000,};// 1. 转成[key,value]数组过滤空值2. 转回对象constfilteredUserObject.fromEntries(Object.entries(userInfo).filter(([key,value])value!));console.log(filteredUser);// {name: 张三, age:28, phone: 13800138000}URL 参数转对象不用再写正则了// 地址栏的参数?name张三age28gender男constsearchStrwindow.location.search.slice(1);// 直接转成对象支持中文和特殊字符constparamObjObject.fromEntries(newURLSearchParams(searchStr));console.log(paramObj);// {name: 张三, age: 28, gender: 男}三、?? 与 ??比 || 靠谱用 || 设置默认值时会把 0、“”、false 这些 “有效假值” 当成空值。而 ?? 只判断 null/undefined。示例处理用户输入的 “有效假值”// 用户输入的数量 0 是有效数值不能替换constuserInputCount0;// 错误会把 0 当成空值返回 10constwrongCountuserInputCount||10;// 正确写法只判断 null/undefined返回 0constcorrectCountuserInputCount??10;console.log(wrongCount,correctCount);// 10, 0给对象补默认值不会覆盖已有值// 前端传入的配置可能缺少 retries 字段constrequestConfig{timeout:5000};// 只有当 retries 为 null/undefined 时才赋值 3不覆盖已有值requestConfig.retries??3;console.log(requestConfig);// {timeout:5000, retries:3}// 如果已有值不会被覆盖constoldConfig{timeout:3000,retries:2};oldConfig.retries??3;console.log(oldConfig);// {timeout:3000, retries:2}四、Intl API原生国际化 API很多人会用 moment.js 处理日期、货币格式化但这个库体积特别大压缩后也有几十 KB而 Intl 是浏览器原生 API支持货币、日期、数字的本地化体积为 0还能自动适配地区。示例多语言货币格式化适配中英文constprice1234.56;// 人民币格式自动加 ¥ 和千分位constcnyPricenewIntl.NumberFormat(zh-CN,{style:currency,currency:CNY,}).format(price);// 美元格式自动加 $ 和千分位constusdPricenewIntl.NumberFormat(en-US,{style:currency,currency:USD,}).format(price);console.log(cnyPrice,usdPrice);// ¥1,234.56 $1,234.56日期本地化不用手动拼接年月日constnownewDate();// 中文日期2025年11月3日 15:40:22constcnDatenewIntl.DateTimeFormat(zh-CN,{year:numeric,month:long,day:numeric,hour:2-digit,minute:2-digit,second:2-digit,}).format(now);// 英文日期November 3, 2025, 03:40:22 PMconstenDatenewIntl.DateTimeFormat(en-US,{year:numeric,month:long,day:numeric,hour:2-digit,minute:2-digit,second:2-digit,}).format(now);console.log(cnDate,enDate);五、Intersection Observer图片懒加载 滚动加载不卡主线程传统我们用 scroll 事件 getBoundingClientRect() 判断元素是否在视口会频繁触发重排导致页面卡顿Intersection Observer API 是异步监听不阻塞主线程性能直接提升一大截。示例图片懒加载可用于优化首屏加载速度html javascript // 初始化观察者 const lazyObserver new IntersectionObserver((entries) { entries.forEach((entry) { // 当图片进入视口 if (entry.isIntersecting) { const img entry.target; img.src img.dataset.src; // 加载真实图片 lazyObserver.unobserve(img); // 加载后停止监听 } }); }); // 给所有懒加载图片添加监听 document.querySelectorAll(.lazy-img).forEach((img) { lazyObserver.observe(img); }); 列表滚动加载更多避免一次性加载过多数据ulidnews-list/ul!-- 加载提示放在列表底部 --dividload-more加载中.../divconstloadObservernewIntersectionObserver((entries){if(entries[0].isIntersecting){// 当加载提示进入视口请求下一页数据fetchNextPageData().then((data){renderNews(data);// 渲染新列表项});}});// 监听加载提示元素loadObserver.observe(document.getElementById(load-more));六、Promise.allSettled ()批量请求不 “挂掉”比 Promise.all 更实用如果使用 Promise.all当批量请求时只要有一个请求失败Promise.all 就会直接 reject其他成功的请求结果就拿不到了而 allSettled 会等待所有请求完成不管成功失败还能分别处理结果。示例批量获取用户信息 订单 消息部分接口失败不影响整体// 3个并行请求可能有失败的constrequestList[fetch(/api/user/101),// 成功fetch(/api/orders/101),// 失败比如订单不存在fetch(/api/messages/101),// 成功];// 等待所有请求完成处理成功和的结果Promise.allSettled(requestList).then((results){// 处理成功的请求constsuccessDataresults.filter((res)res.statusfulfilled).map((res)res.value.json());// 记录失败的请求方便排查问题constfailedRequestsresults.filter((res)res.statusrejected).map((res)res.reason.url);console.log(成功数据,successData);console.log(失败接口,failedRequests);// [/api/orders/101]});七、element.closest ()向上找父元素最安全的方式传统如果想找某个元素的父元素比如点击列表项找列表需要使用 element.parentNode.parentNode但一旦 DOM 结构变了代码就崩了closest() 会直接根据 CSS 选择器找最近的祖先元素不管嵌套多少层。示例点击列表项给列表容器加高亮ulclassuser-listliclassuser-item张三/liliclassuser-item李四/li/uldocument.querySelectorAll(.user-item).forEach((item){item.addEventListener(click,(e){// 找到最近的.user-list不管中间嵌套多少层constliste.target.closest(.user-list);list.classList.toggle(active);// 切换高亮});});输入框聚焦给表单组加样式divclassform-grouplabel用户名/labelinputtypetextidusername//divconstusernameInputdocument.getElementById(username);usernameInput.addEventListener(focus,(e){// 找到最近的.form-group加focused样式constformGroupe.target.closest(.form-group);formGroup.classList.add(focused);});八、URL URLSearchParams处理 URL 方便多了传统解析 URL 参数、修改参数还要写复杂的正则表达式有时还得处理中文编码问题URL API 可以直接解析 URL 结构URLSearchParams 可用于处理参数支持增删改查自动编码方便多了。示例解析 URL 参数支持中文和特殊字符// 当前页面URLhttps://xxx.com/user?name张三age28gender男constcurrentUrlnewURL(window.location.href);// 获取参数console.log(currentUrl.searchParams.get(name));// 张三console.log(currentUrl.hostname);// xxx.com域名console.log(currentUrl.pathname);// /user路径修改 URL 参数跳转新页面consturlnewURL(https://xxx.com/list);// 添加参数url.searchParams.append(page,2);url.searchParams.append(size,10);// 修改参数url.searchParams.set(page,3);// 删除参数url.searchParams.delete(size);console.log(url.href);// https://xxx.com/list?page3window.location.hrefurl.href;// 跳转到第3页九、for…of 循环比 forEach 灵活还支持 break 和 continueforEach 不能用 break 中断循环也不能用 continue 跳过当前项。而 for…of 不仅支持中断还能遍历数组、Set、Map、字符串甚至获取索引。示例遍历数组找到目标值后中断constproductList[{id:1,name:手机,price:5999},{id:2,name:电脑,price:9999},{id:3,name:平板,price:3999},];// 找价格大于8000的产品找到后中断for(constproductofproductList){if(product.price8000){console.log(找到高价产品,product);// {id:2, name:电脑, ...}break;// 中断循环不用遍历剩下的}}遍历 Set获取索引constuniqueTagsnewSet([前端,JS,CSS]);// 用 entries() 获取索引和值for(const[index,tag]of[...uniqueTags].entries()){console.log(索引${index}${tag});// 索引 0前端索引 1JS...}十、顶层 await模块异步初始化以前在 ES 模块里想异步加载配置必须写个 async 函数再调用现在 top-level await 允许你在模块顶层直接用 await其他模块导入时会自动等待不用再手动处理异步。示例模块初始化时加载配置// config.js// 顶层直接 await加载后端配置constresponseawaitfetch(/api/config);exportconstappConfigawaitresponse.json();// {baseUrl: https://xxx.com, timeout: 5000}// api.js导入 config.js自动等待配置加载完成import{appConfig}from./config.js;// 直接用配置不用关心异步exportconstapiClient{baseUrl:appConfig.baseUrl,get(url){returnfetch(${this.baseUrl}${url},{timeout:appConfig.timeout});},};点击按钮动态加载组件按需加载减少首屏体积// 点击“图表”按钮才加载图表组件document.getElementById(show-chart-btn).addEventListener(click,async(){// 动态导入图表模块await 等待加载完成const{renderChart}awaitimport(./chart-module.js);renderChart(#chart-container);// 渲染图表});结语可以看到以前我们依赖的第三方库其实原生 API 早就能解决比如用 Intl 替代 moment.js用 Set 替代 lodash 的 uniq用 Intersection Observer 替代懒加载随着老旧的浏览器被 内容过长

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询