15个 JavaScript 技巧,让你在2026年成为更好的开发者

发布: (2026年3月29日 GMT+8 05:29)
6 分钟阅读
原文: Dev.to

Source: Dev.to

这些 JavaScript 小技巧真的提升了我的代码质量。没有废话——只有有效的模式。

1. 可选链是你的最佳伙伴

// Old way – ugly and error‑prone
const city = user && user.address && user.address.city;

// Modern way
const city = user?.address?.city;

// With methods
const first = arr?.at(0);
const len   = str?.trim()?.length;

2. Nullish Coalescing vs OR

// || 使用任何 falsy 值(0、''、false 都是 falsy!)
const count = data.count || 10; // BUG: 当 count 为 0 时返回 10

// ?? 仅在 null/undefined 时触发
const count = data.count ?? 10; // CORRECT: 当 count 为 0 时返回 0

3. 对象解构并设默认值

function createUser({
  name,
  role = 'user',
  active = true,
  theme = 'light'
} = {}) {
  return { name, role, active, theme };
}

// The = {} default allows calling with no arguments
createUser(); // Works!
createUser({ name: 'Alice' });
// { name: 'Alice', role: 'user', active: true, theme: 'light' }

4. 使用数组方法替代循环

const users = [
  { name: 'Alice',   age: 25, active: true },
  { name: 'Bob',     age: 30, active: false },
  { name: 'Charlie', age: 22, active: true }
];

// Get names of active users over 24, sorted alphabetically
const result = users
  .filter(u => u.active && u.age > 24)
  .map(u => u.name)
  .sort();

// Result: ['Alice']

结果: [‘Alice’]

5. Promise.allSettled 并行请求

// Promise.all fails if ANY request fails
// Promise.allSettled waits for all, reports success/failure for each

const results = await Promise.allSettled([
  fetch('/api/users'),
  fetch('/api/posts'),
  fetch('/api/comments')
]);

results.forEach((result, index) => {
  if (result.status === 'fulfilled') {
    console.log(`Request ${index}: success`);
  } else {
    console.log(`Request ${index}: failed - ${result.reason}`);
  }
});

6. 用于私有数据的 WeakMap

const privateData = new WeakMap();

class User {
  constructor(name, password) {
    privateData.set(this, { password });
    this.name = name;
  }

  checkPassword(input) {
    return privateData.get(this).password === input;
  }
}

const user = new User('Alice', 'secret123');
console.log(user.checkPassword('secret123')); // true
console.log(user.password); // undefined – truly private!

7. Object.fromEntries 用于转换

const prices = { apple: 1.5, banana: 0.5, cherry: 3.0 };

// Apply 10 % discount to all
const discounted = Object.fromEntries(
  Object.entries(prices).map(([key, value]) => [key, value * 0.9])
);

// { apple: 1.35, banana: 0.45, cherry: 2.7 }

8. 逻辑赋值运算符

// ||= 仅在左侧为 falsy 时赋值
user.role ||= 'guest';

// &&= 仅在左侧为 truthy 时赋值
user.profile &&= updateProfile(user.profile);

// ??= 仅在左侧为 null/undefined 时赋值
config.timeout ??= 3000;

9. Array.at() 用于负索引

const arr = [1, 2, 3, 4, 5];

// Old way
const last = arr[arr.length - 1]; // 5

// Modern way
const last       = arr.at(-1); // 5
const secondLast = arr.at(-2); // 4

10. 结构化克隆用于深拷贝

// JSON.parse(JSON.stringify()) 会破坏日期、函数等。
const shallow = { ...obj }; // 仅进行浅拷贝

// 正确的深拷贝(Node 17+,所有现代浏览器)
const deep = structuredClone(obj);

11. AbortController 用于请求取消

async function fetchWithTimeout(url, timeout = 5000) {
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), timeout);

  try {
    const response = await fetch(url, { signal: controller.signal });
    clearTimeout(timeoutId);
    return response.json();
  } catch (err) {
    if (err.name === 'AbortError') {
      throw new Error('Request timed out');
    }
    throw err;
  }
}

12. 生成器函数用于惰性序列

function* fibonacci() {
  let [a, b] = [0, 1];
  while (true) {
    yield a;
    [a, b] = [b, a + b];
  }
}

const fib = fibonacci();
const first10 = Array.from({ length: 10 }, () => fib.next().value);
// [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

13. 更好的调试错误原因

async function fetchUser(id) {
  try {
    const data = await db.query('SELECT * FROM users WHERE id = ?', [id]);
    return data;
  } catch (err) {
    throw new Error(`Failed to fetch user ${id}`, { cause: err });
  }
}

// Now you can access the original error
try {
  await fetchUser(42);
} catch (err) {
  console.log(err.message); // "Failed to fetch user 42"
  console.log(err.cause);   // Original DB error
}

14. 使用 Object.groupBy 进行数组分组

const inventory = [
  { name: 'asparagus', type: 'vegetables', quantity: 5 },
  { name: 'bananas',   type: 'fruit',       quantity: 0 },
  // ... (rest of the data)
];

// Example usage (requires a recent JS engine):
const grouped = Object.groupBy(inventory, item => item.type);
// {
//   vegetables: [{ name: 'asparagus', type: 'vegetables', quantity: 5 }],
//   fruit:      [{ name: 'bananas',   type: 'fruit',       quantity: 0 }],
//   // …
}
const inventory = [
  { name: 'asparagus', type: 'vegetables', quantity: 1 },
  { name: 'bananas',   type: 'fruit',      quantity: 5 },
  { name: 'cherries',  type: 'fruit',      quantity: 2 },
  { name: 'carrots',   type: 'vegetables', quantity: 1 },
];

const grouped = Object.groupBy(inventory, ({ type }) => type);
// {
//   vegetables: [asparagus, carrots],
//   fruit:      [bananas, cherries]
// }

15. 更好地使用 console

// Group related logs
console.group('User Authentication');
console.log('Checking credentials...');
console.log('Token validated');
console.groupEnd();

// Time operations
console.time('db-query');
await db.query('...');
console.timeEnd('db-query'); // db-query: 23.4ms

// Table for arrays/objects
console.table(users);

// Assert (throws if false)
console.assert(user.id > 0, 'User ID must be positive');

关键要点

  • 使用 ?.?? 代替手动的空值检查。
  • 当需要 全部 结果时,优先使用 Promise.allSettled
  • 使用 structuredClone 进行深拷贝。
  • 接受新语法——它在所有现代浏览器中都受支持。

这些中哪一点对你是新鲜的? 在评论中告诉我!

关注我,获取每周 JavaScript 与网页开发技巧。

0 浏览
Back to Blog

相关文章

阅读更多 »

网络怀旧

概述 我一直对互联网的快速演变感到着迷。从90年代那种杂乱、色彩斑斓的网站,到今天的简洁、极简设计——它……