10个实用的JavaScript功能,帮你写出更简洁的代码

摘要:JavaScript有很多好用但容易被忽略的功能。合理使用这些功能,不仅能减少代码量,还能提高程序运行效率。下面介绍10个值得尝试的JavaScript特性。

JavaScript有很多好用但容易被忽略的功能。合理使用这些功能,不仅能减少代码量,还能提高程序运行效率。下面介绍10个值得尝试的JavaScript特性。


1. Set:快速去重和查找

处理重复数据时,Set比传统方法快很多。Set自动保证值的唯一性,查找速度也很快。

数组去重可以这样写:

const duplicateIds = [101, 102, 102, 103, 103, 103];
const uniqueIds = [...new Set(duplicateIds)];
console.log(uniqueIds); // [101, 102, 103]

防止重复添加事件监听器:

const listenedEvents = new Set();

function safeAddEvent(eventName, handler) {
  if (!listenedEvents.has(eventName)) {
    window.addEventListener(eventName, handler);
    listenedEvents.add(eventName);
  }
}

// 多次调用也只会绑定一次
safeAddEvent("scroll", () => console.log("页面滚动"));
safeAddEvent("scroll", () => console.log("页面滚动"));


2. Object.entries和Object.fromEntries:对象和数组互相转换

这对方法让对象操作变得简单。

过滤对象中的空值:

const userInfo = {
  name: "张三",
  age: 28,
  avatar: "",
  phone: "13800138000"
};

const filteredUser = Object.fromEntries(
  Object.entries(userInfo).filter(([key, value]) => value !== "")
);
console.log(filteredUser); // {name: "张三", age: 28, phone: "13800138000"}

解析URL参数:

const searchStr = "name=张三&age=28&gender=男";
const paramObj = Object.fromEntries(new URLSearchParams(searchStr));
console.log(paramObj); // {name: "张三", age: "28", gender: "男"}


3. ?? 和 ??=:更安全的默认值设置

传统的||操作符会把0、空字符串等有效值当成false,??只对null和undefined起作用。

设置默认值:

const userInputCount = 0;

// 错误写法:会把0替换成10
const wrongCount = userInputCount || 10;

// 正确写法:保留0
const correctCount = userInputCount ?? 10;

console.log(wrongCount, correctCount); // 10, 0

给对象设置默认属性:

const requestConfig = { timeout: 5000 };

// 只有当retries为null或undefined时才设置默认值
requestConfig.retries ??= 3;
console.log(requestConfig); // {timeout: 5000, retries: 3}


4. Intl API:内置的国际化功能

不需要引入额外的库,浏览器原生支持多语言格式化。

货币格式化:

const price = 1234.56;

// 人民币格式
const cnyPrice = new Intl.NumberFormat("zh-CN", {
  style: "currency",
  currency: "CNY"
}).format(price);

// 美元格式
const usdPrice = new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "USD"
}).format(price);

console.log(cnyPrice, usdPrice); // ¥1,234.56 $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);

console.log(cnDate); // 2024年11月3日 15:40:22


5. Intersection Observer:高效的元素可见性检测

传统的滚动检测会影响页面性能,这个API可以异步监听元素是否进入视口。

图片懒加载:

<img >="real-image.jpg" src="placeholder.jpg" class="lazy-img">
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);
});


6. Promise.allSettled:更友好的并行请求处理

Promise.all在有一个请求失败时就会全部失败,allSettled会等待所有请求完成。

批量请求处理:

const requestList = [
  fetch("/api/user/101"),
  fetch("/api/orders/101"),
  fetch("/api/messages/101")
];

Promise.allSettled(requestList).then((results) => {
  const successData = results
    .filter(res => res.status === "fulfilled")
    .map(res => res.value);
    
  const failedRequests = results
    .filter(res => res.status === "rejected")
    .map(res => res.reason);
    
  console.log("成功的数据:", successData);
  console.log("失败的请求:", failedRequests);
});


7. element.closest:查找父元素的简单方法

不需要手动遍历父元素,直接用选择器查找最近的匹配祖先元素。

点击列表项找到列表容器:

document.querySelectorAll(".user-item").forEach((item) => {
  item.addEventListener("click", (e) => {
    const list = e.target.closest(".user-list");
    list.classList.toggle("active");
  });
});


8. URL和URLSearchParams:专业的URL处理

解析和操作URL不再需要复杂的正则表达式。

解析当前页面URL:

const currentUrl = new URL(window.location.href);
console.log(currentUrl.searchParams.get("name")); // 获取参数
console.log(currentUrl.hostname); // 域名

构建新的URL:

const url = new URL("https://shenqiku.cn/list");
url.searchParams.append("page", 2);
url.searchParams.set("size", 10);

console.log(url.href); // https://shenqiku.cn/list?page=2&size=10


9. for...of循环:灵活的遍历方式

支持break和continue,可以遍历多种数据类型。

在数组中查找特定元素:

const productList = [
  { id: 1, name: "手机", price: 5999 },
  { id: 2, name: "电脑", price: 9999 },
  { id: 3, name: "平板", price: 3999 }
];

for (const product of productList) {
  if (product.price > 8000) {
    console.log("找到高价产品:", product);
    break; // 找到后停止循环
  }
}


10. 顶层await:简化模块的异步初始化

在模块顶层直接使用await,导入时会自动等待异步操作完成。

异步加载配置:

// config.js
const response = await fetch("/api/config");
export const appConfig = await response.json();

// 其他文件导入时会自动等待配置加载完成
import { appConfig } from "./config.js";

按需加载模块:

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


总结

这些JavaScript功能在现代浏览器中都有很好的支持。它们可以帮助我们:

  • 减少第三方库的使用依赖
  • 提高代码运行效率
  • 让代码更简洁易读

在实际项目中,根据具体需求选择合适的特性,能够显著提升开发效率和代码质量。建议从Set、??操作符等简单功能开始尝试,逐步在项目中应用更多实用特性。

本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://shenqiku.cn/article/FLY_13142