JavaScript特性笔记

1. Set 数组去重

// 事件监听防重复
const listenedEvents = new Set();
function safeAddEvent(eventName, handler) {
    if (!listenedEvents.has(eventName)) {
        window.addEventListener(eventName, handler);
        listenedEvents.add(eventName);
    }
}

2. Object.entries() + Object.fromEntries()

用法:对象⇄数组双向转换,实现高级操作

// URL参数转对象
const searchStr = "name=张三&age=28";
const paramObj = Object.fromEntries(new URLSearchParams(searchStr));
console.log(paramObj); // {name: "张三", age: "28"}

3.空值合并运算符 (??) 和赋值 (??=)

用法:只对 null 和 undefined 生效,不误判有效假值

// ?? 替换 ||
const userInputCount = 0;
const wrongCount = userInputCount || 10; // 10 (错误)
const correctCount = userInputCount ?? 10; // 0 (正确)

// 对象默认值(不覆盖已有值)
const requestConfig = { timeout: 5000 };
requestConfig.retries ??= 3; // 添加默认值
console.log(requestConfig); // {timeout: 5000, retries: 3}

4.Intl 国际化 API

用法:浏览器原生国际化,替代 moment.js 等重型库

// 多语言货币格式化
const price = 1234.56;
const cnyPrice = new Intl.NumberFormat("zh-CN", {
    style: "currency",
    currency: "CNY"
}).format(price); // "¥1,234.56"

// 日期本地化
const now = new Date();
const cnDate = new Intl.DateTimeFormat("zh-CN", {
    year: "numeric",
    month: "long", 
    day: "numeric",
    hour: "2-digit",
    minute: "2-digit",
    second: "2-digit"
}).format(now); // "2024年5月30日 14:30:25"

5.Intersection Observer API

用法:异步监听元素可见性,性能远超传统方法,实现图片懒加载和图片无限滚动加载
// todo 下面的代码可以写成工具

// 图片懒加载
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);
});

// 无限滚动加载
const loadObserver = new IntersectionObserver((entries) => {
    if (entries[0].isIntersecting) {
        fetchNextPageData().then((data) => {
            renderNews(data);
        });
    }
});
loadObserver.observe(document.getElementById("load-more"));

6. Promise.allSettled()

用法:等待所有 Promise 完成,不因单个失败而中断,Promise.all单个失败则终止

7. Element.closest()

用法:基于 CSS 选择器查找最近的祖先元素

// 输入框聚焦找到表单组
document.querySelector("input").addEventListener("focus", (e) => {
    const formGroup = e.target.closest(".form-group");
    formGroup.classList.add("focused");
});

8. URL + URLSearchParams

用法:原生URL处理,解析url和params

// 当前页面URL:https://xxx.com/user?name=张三&age=28&gender=男
const currentUrl = new URL(window.location.href);

// 获取参数
console.log(currentUrl.searchParams.get("name")); // "张三"
console.log(currentUrl.hostname); // "xxx.com"
console.log(currentUrl.pathname); // "/user"

// 修改URL参数
const url = new URL("https://xxx.com/list");

// 增删改查参数
url.searchParams.append("page", 2); // 添加
url.searchParams.set("page", 3); // 修改
url.searchParams.delete("size"); // 删除

console.log(url.href); // "https://xxx.com/list?page=3"
window.location.href = url.href; // 跳转

9. for...of 循环

用法:支持 break/continue,可遍历map、set

10. 顶层 await

用法:允许在模块的最外层直接使用await,而不需要包裹在async函数里
需要注意:顶层 await 会阻塞模块的执行,因此要谨慎使用

  • 案例1:从服务器获取配置
// config.js
const response = await fetch('/api/config');
export const config = await response.json();

// app.js
import { config } from './config.js';
console.log(config); // 这里使用的 config 已经是获取到的配置,不需要担心异步问题
  • 案例2:动态按需加载
// chart-module.js 模块本身在加载时执行一些异步操作,比如加载图表库,那么我们可以这样

const ChartLibrary = await import('https://example.com/chart-library.js');// 动态导入图表库
export function renderChart(container) {
// 使用 ChartLibrary 渲染图表
}

// main.js
document.getElementById('show-chart-btn').addEventListener('click', async () => {
const { renderChart } = await import('./chart-module.js');
renderChart('#chart-container');
});

原文地址

https://mp.weixin.qq.com/s/P7YV9tSi5GfhpL2uD9ojMg

posted @ 2025-11-12 11:35  卷叶小树  阅读(4)  评论(0)    收藏  举报