分享几个我珍藏的JS冷门但实用的技巧

作为一名前端开发者,我在日常工作中发现了一些不太常见但极其实用的JavaScript技巧。这些技巧帮我解决了不少棘手问题,今天就来分享给大家。

1. 使用 ??= 进行逻辑空赋值

你可能熟悉 ||=,但 ??= 才是更精准的选择。它只在变量为 nullundefined 时才赋值:

// 传统写法
let user = { name: "小明" };
if (user.age === null || user.age === undefined) {
  user.age = 18;
}

// 使用 ??=
user.age ??= 18; // 仅在 age 为 null 或 undefined 时赋值

||= 不同,??= 不会在值为 0false 或空字符串时覆盖,这在实际开发中更加安全。

2. 利用 Intl 对象进行本地化处理

处理日期、数字和货币格式化时,Intl 对象是我的秘密武器:

// 数字格式化
const number = 1234567.89;
console.log(new Intl.NumberFormat('zh-CN').format(number)); // "1,234,567.89"

// 货币格式化
console.log(
  new Intl.NumberFormat('zh-CN', { 
    style: 'currency', 
    currency: 'CNY' 
  }).format(number)
); // "¥1,234,567.89"

// 相对时间格式化(这个特别实用)
const rtf = new Intl.RelativeTimeFormat('zh-CN', { numeric: 'auto' });
console.log(rtf.format(-1, 'day')); // "昨天"
console.log(rtf.format(5, 'hour')); // "5小时后"

3. 使用 flatMap 进行过滤和映射

我经常用 flatMap 来替代 filter + map 的组合,代码更简洁:

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

// 传统方式:筛选偶数并加倍
const result1 = numbers
  .filter(n => n % 2 === 0)
  .map(n => n * 2);

// 使用 flatMap:一步到位
const result2 = numbers.flatMap(n => 
  n % 2 === 0 ? [n * 2] : []
);

console.log(result1); // [4, 8]
console.log(result2); // [4, 8] 结果相同!

4. 标签模板字面量的妙用

除了基本的字符串插值,标签模板还能做很多有趣的事情:

// 简单的SQL转义(注意:生产环境请使用专业库)
function sql(strings, ...values) {
  return strings.reduce((result, str, i) => {
    const value = values[i] !== undefined ? 
      `'${String(values[i]).replace(/'/g, "''")}'` : '';
    return result + str + value;
  }, '');
}

const userId = 123;
const userName = "O'Reilly";
const query = sql`SELECT * FROM users WHERE id = ${userId} AND name = ${userName}`;
console.log(query); 
// "SELECT * FROM users WHERE id = '123' AND name = 'O''Reilly'"

5. 使用 Proxy 实现优雅的对象监听

Proxy 让我能够创建具有自定义行为的对象:

function createObservable(target, callback) {
  return new Proxy(target, {
    set(obj, prop, value) {
      const oldValue = obj[prop];
      obj[prop] = value;
      callback(prop, oldValue, value);
      return true;
    }
  });
}

const user = createObservable({ name: "小明" }, (prop, oldVal, newVal) => {
  console.log(`属性 ${prop} 从 ${oldVal} 变为 ${newVal}`);
});

user.name = "小红"; // 控制台输出: "属性 name 从 小明 变为 小红"
user.age = 18;     // 控制台输出: "属性 age 从 undefined 变为 18"

6. 利用 WeakMap 实现私有属性

在ES6类中实现真正的私有属性:

const privateData = new WeakMap();

class Person {
  constructor(name, age) {
    // 将私有数据存储在WeakMap中,键为当前实例
    privateData.set(this, { name, age });
  }
  
  getName() {
    return privateData.get(this).name;
  }
  
  getAge() {
    return privateData.get(this).age;
  }
}

const person = new Person("小明", 25);
console.log(person.getName()); // "小明"
console.log(person.name);      // undefined - 真正私有的!

7. 使用 Array.from 进行复杂数组操作

Array.from 的第二个参数是个映射函数,功能强大:

// 创建数字序列
const range = (start, end) => 
  Array.from({ length: end - start + 1 }, (_, i) => start + i);

console.log(range(5, 10)); // [5, 6, 7, 8, 9, 10]

// 创建字母序列
const alphabet = (start, end) => 
  Array.from({ length: end.charCodeAt(0) - start.charCodeAt(0) + 1 }, 
    (_, i) => String.fromCharCode(start.charCodeAt(0) + i));

console.log(alphabet('A', 'F')); // ['A', 'B', 'C', 'D', 'E', 'F']

8. 使用 Object.fromEntries 进行对象转换

这个方法是 Object.entries 的逆操作,非常适合数据转换:

// 将URL查询参数转换为对象
const queryString = "name=小明&age=25&city=北京";
const searchParams = new URLSearchParams(queryString);
const queryObject = Object.fromEntries(searchParams);
console.log(queryObject); 
// { name: "小明", age: "25", city: "北京" }

// 数组转对象
const pairs = [['width', 100], ['height', 200]];
const dimensions = Object.fromEntries(pairs);
console.log(dimensions); // { width: 100, height: 200 }

结语

这些技巧在我日常开发中帮了大忙,希望它们对你也有所启发。JavaScript的世界总是在不断进化,保持学习和探索的心态,你会发现更多有趣的特性。

如果你也有什么珍藏的JS技巧,欢迎在评论区分享!

posted @ 2025-10-30 09:02  深圳蔓延科技有限公司  阅读(10)  评论(0)    收藏  举报