9 dòng lệnh JavaScript thay thế 50 dòng code

Đối với những lập trình viên, chắc hẳn đã không ít lần bạn nhìn vào những đoạn code JavaScript phức tạp và cảm thấy bối rối. Có lẽ bạn đã tự hỏi liệu có cách nào tốt hơn để thực hiện các tác vụ mà không cần phải viết quá nhiều dòng lệnh.

9 dòng lệnh JavaScript thay thế 50 dòng code

1. Làm phẳng mảng lồng nhau

Nếu bạn đã từng cố gắng làm phẳng một mảng lồng nhau, bạn sẽ biết rằng điều này thường rất phức tạp với nhiều vòng lặp. Tuy nhiên, với phương thức flat(), quy trình này dễ dàng hơn rất nhiều:

const flattenArray = arr => arr.flat(Infinity);

const nestedArray = [1, [2, 3, [4, 5, [6, 7]]], 8, [9, 10]];
const cleanArray = flattenArray(nestedArray);
// Kết quả: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Cách truyền thống:

Nếu làm theo cách thủ công, bạn có thể thấy đoạn code dưới đây:

function flattenTheHardWay(arr) {
  let result = [];
  for (let i = 0; i < arr.length; i++) {
    if (Array.isArray(arr[i])) {
      result = result.concat(flattenTheHardWay(arr[i]));
    } else {
      result.push(arr[i]);
    }
  }
  return result;
}

Với flat(Infinity), bạn có thể làm phẳng mảng ở bất kỳ cấp độ nào một cách dễ dàng.

2. Sao chép sâu đối tượng không cần thư viện

Để tạo một bản sao sâu của một đối tượng mà không cần sử dụng thư viện bên ngoài, bạn có thể sử dụng JSON.parseJSON.stringify như sau:

const deepClone = obj => JSON.parse(JSON.stringify(obj));

const complexObj = {
  user: { name: 'Alex', date: new Date() },
  scores: [1, 2, [3, 4]],
  active: true
};
const cloned = deepClone(complexObj);

Cách cũ:

function manualDeepClone(obj) {
  if (obj === null || typeof obj !== 'object') return obj;
  if (obj instanceof Date) return new Date(obj);

  const clone = Array.isArray(obj) ? [] : {};

  for (let key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      clone[key] = manualDeepClone(obj[key]);
    }
  }
  return clone;
}

Lưu ý rằng giải pháp này có một số giới hạn, không hoạt động với ký hiệu, hàm hoặc các tham chiếu vòng.

3. Chuyển đổi CSV sang mảng đối tượng

Một cách nhanh chóng để chuyển đổi dữ liệu CSV thành mảng các đối tượng dễ thao tác:

const csvToObjects = csv => csv.split('\n').map(row => Object.fromEntries(row.split(',').map((value, i, arr) => [arr[0].split(',')[i], value])));

const csvData = `name,age,city
Peboy,30,New York
Peace,25,San Francisco
Lara,35,Chicago`;

const parsed = csvToObjects(csvData);
// Kết quả:
// [
//   { name: 'Peboy', age: '30', city: 'New York' },
//   { name: 'Peace', age: '25', city: 'San Francisco' },
//   { name: 'Lara', age: '35', city: 'Chicago' }
// ]

Cách truyền thống:

function convertCSVTheHardWay(csv) {
  const lines = csv.split('\n');
  const headers = lines[0].split(',');
  const result = [];

  for (let i = 1; i < lines.length; i++) {
    const obj = {};
    const currentLine = lines[i].split(',');

    for (let j = 0; j < headers.length; j++) {
      obj[headers[j]] = currentLine[j];
    }
    result.push(obj);
  }
  return result;
}

Trải nghiệm chuyển đổi này sẽ tốt hơn khi bạn thêm xử lý lỗi trong sản xuất.

4. Xóa phần tử trùng lặp và sắp xếp mảng

Loại bỏ các phần tử trùng lặp và sắp xếp mảng chỉ với một dòng lệnh:

const uniqueSorted = arr => [...new Set(arr)].sort((a, b) => a - b);

// Ví dụ sử dụng:
const messyArray = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5];
const cleaned = uniqueSorted(messyArray);
// Kết quả: [1, 2, 3, 4, 5, 6, 9]

Cách cũ:

function cleanArrayManually(arr) {
  const unique = [];
  for (let i = 0; i < arr.length; i++) {
    if (unique.indexOf(arr[i]) === -1) {
      unique.push(arr[i]);
    }
  }
  return unique.sort((a, b) => a - b);
}

5. Thao tác DOM: Truy vấn và biến đổi nhiều phần tử

Truy vấn và biến đổi nhiều phần tử DOM đồng thời:

const modifyElements = selector => Array.from(document.querySelectorAll(selector)).forEach(el => {
  el.style.backgroundColor = '#007bff';
  el.style.color = 'white';
  el.style.padding = '10px 20px';
});

// Sử dụng:
modifyElements('.btn');

Cách truyền thống:

function updateElementsManually(selector) {
  const elements = document.querySelectorAll(selector);
  for (let i = 0; i < elements.length; i++) {
    const el = elements[i];
    el.style.backgroundColor = '#007bff';
    el.style.color = 'white';
    el.style.padding = '10px 20px';
  }
}

6. Gọi API song song với xử lý lỗi sạch

Thực hiện các lệnh gọi song song tới API:

const parallelCalls = urls => Promise.allSettled(urls.map(url => fetch(url).then(r => r.json())));

const urls = [
  'https://api.example.com/users',
  'https://api.example.com/posts',
  'https://api.example.com/comments'
];

const getData = async () => {
  const results = await parallelCalls(urls);
  const [users, posts, comments] = results.map(r => r.status === 'fulfilled' ? r.value : null);
};

Cách truyền thống:

async function fetchDataManually(urls) {
  const results = [];
  for (const url of urls) {
    try {
      const response = await fetch(url);
      const data = await response.json();
      results.push({ status: 'fulfilled', value: data });
    } catch (error) {
      results.push({ status: 'rejected', reason: error });
    }
  }
  return results;
}

7. Định dạng ngày/giờ: Chuỗi ngày tháng gọn gàng không cần thư viện

Biến đổi ngày tháng thành chuỗi dễ đọc:

const formatDate = date => new Intl.DateTimeFormat('en-US', { dateStyle: 'full', timeStyle: 'short' }).format(date);

const now = new Date();
console.log(formatDate(now));
// Output: "Thursday, December 9, 2024 at 2:30 PM"

Cách cũ:

function formatDateManually(date) {
  const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
  const months = [...];

  const dayName = days[date.getDay()];
  const monthName = months[date.getMonth()];
  // Còn lại...
}

8. Xử lý sự kiện: Debounce không cần Bloat

Tạo phiên bản debounce cho bất kỳ hàm nào mà không cần quá phức tạp:

const debounce = (fn, ms) => {
  let timeout;
  return (...args) => {
    clearTimeout(timeout);
    timeout = setTimeout(() => fn(...args), ms);
  };
};

// Ví dụ sử dụng:
const expensiveSearch = query => console.log('Searching for:', query);
const debouncedSearch = debounce(expensiveSearch, 300);

searchInput.addEventListener('input', e => debouncedSearch(e.target.value));

Cách cũ:

function createDebounce(fn, delay) {
  let timeoutId;
  return function debounced(...args) {
    // Còn lại...
  };
}

9. Lưu trữ cục bộ: Lưu trữ đối tượng với xác thực

Xử lý lưu trữ đối tượng trong localStorage với xác thực:

const store = key => ({
  get: () => JSON.parse(localStorage.getItem(key)),
  set: data => localStorage.setItem(key, JSON.stringify(data)),
  remove: () => localStorage.removeItem(key)
});

// Sử dụng:
const userStore = store('user');
userStore.set({ id: 1, name: 'John', preferences: { theme: 'dark' } });
const userData = userStore.get();
userStore.remove();

Cách cũ:

function handleLocalStorage(key) {
  return {
    get: function() { /* Còn lại... */ },
    set: function(data) { /* Còn lại... */ },
    remove: function() { /* Còn lại... */ }
  };
}

Kết luận

Những thủ thuật trên không chỉ giúp bạn giảm số lượng dòng code mà còn giúp bạn viết code một cách thông minh hơn. Hãy nhớ rằng khả năng đọc hiểu cũng rất quan trọng. Nếu bất kỳ đoạn code nào trở nên khó hiểu, hãy chia nó thành nhiều dòng.

Chúc bạn ứng dụng thành công những mẹo này trong các dự án của mình! Nhớ kiểm tra khả năng tương thích trình duyệt với các tính năng mới của JavaScript nếu bạn cần hỗ trợ trình duyệt cũ hơn nhé!