JavaScript ES2024: Fitur-Fitur Baru yang Wajib Diketahui Developer

JavaScript ES2024: Fitur-Fitur Baru yang Wajib Diketahui Developer

JavaScript terus berkembang dengan fitur-fitur baru yang memudahkan developer. ES2024 (ECMAScript 2024) membawa beberapa addition yang sangat berguna untuk development modern.

1. Array Grouping dengan Object.groupBy()

Fitur yang sangat dinanti untuk mengelompokkan array berdasarkan kriteria tertentu:

const products = [
  { name: 'Laptop', category: 'Electronics', price: 1000 },
  { name: 'Shirt', category: 'Clothing', price: 50 },
  { name: 'Phone', category: 'Electronics', price: 800 },
  { name: 'Jeans', category: 'Clothing', price: 80 }
];

// Grouping by category
const groupedByCategory = Object.groupBy(products, product => product.category);

console.log(groupedByCategory);
// {
//   Electronics: [
//     { name: 'Laptop', category: 'Electronics', price: 1000 },
//     { name: 'Phone', category: 'Electronics', price: 800 }
//   ],
//   Clothing: [
//     { name: 'Shirt', category: 'Clothing', price: 50 },
//     { name: 'Jeans', category: 'Clothing', price: 80 }
//   ]
// }

Use Cases Praktis

// Group users by age range
const users = [
  { name: 'Alice', age: 25 },
  { name: 'Bob', age: 35 },
  { name: 'Charlie', age: 28 }
];

const groupedByAgeRange = Object.groupBy(users, user => {
  if (user.age < 30) return 'Young';
  if (user.age < 40) return 'Middle';
  return 'Senior';
});

2. Map.groupBy() untuk Map Objects

Similar dengan Object.groupBy(), tapi return Map instead:

const transactions = [
  { id: 1, type: 'income', amount: 1000 },
  { id: 2, type: 'expense', amount: 500 },
  { id: 3, type: 'income', amount: 750 }
];

const groupedTransactions = Map.groupBy(transactions, t => t.type);

console.log(groupedTransactions.get('income'));
// [{ id: 1, type: 'income', amount: 1000 }, { id: 3, type: 'income', amount: 750 }]

3. Promise.withResolvers()

Cara baru untuk membuat Promise dengan resolver dan rejecter yang exposed:

// Old way
let resolve, reject;
const promise = new Promise((res, rej) => {
  resolve = res;
  reject = rej;
});

// New way with Promise.withResolvers()
const { promise, resolve, reject } = Promise.withResolvers();

// Practical example
function createTimeoutPromise(delay) {
  const { promise, resolve } = Promise.withResolvers();
  
  setTimeout(() => {
    resolve(`Completed after ${delay}ms`);
  }, delay);
  
  return promise;
}

// Usage
createTimeoutPromise(1000).then(console.log);

Real-world Example

class EventEmitter {
  constructor() {
    this.listeners = new Map();
  }
  
  waitForEvent(eventName) {
    const { promise, resolve } = Promise.withResolvers();
    
    const listener = (data) => {
      resolve(data);
      this.off(eventName, listener);
    };
    
    this.on(eventName, listener);
    return promise;
  }
}

4. Atomics.waitAsync()

Non-blocking version dari Atomics.wait():

// Shared memory between workers
const sharedBuffer = new SharedArrayBuffer(1024);
const sharedArray = new Int32Array(sharedBuffer);

// Non-blocking wait
const result = Atomics.waitAsync(sharedArray, 0, 0);

if (result.async) {
  result.value.then(() => {
    console.log('Value changed!');
  });
} else {
  console.log('Value already changed');
}

5. String.prototype.isWellFormed()

Check apakah string memiliki well-formed Unicode:

const validString = "Hello 👋";
const invalidString = "\uD800"; // Lone surrogate

console.log(validString.isWellFormed()); // true
console.log(invalidString.isWellFormed()); // false

// Practical usage
function safeStringOperation(str) {
  if (!str.isWellFormed()) {
    throw new Error('Invalid Unicode string');
  }
  
  return str.toWellFormed();
}

6. String.prototype.toWellFormed()

Convert string menjadi well-formed Unicode:

const malformedString = "Hello\uD800World";
const wellFormedString = malformedString.toWellFormed();

console.log(wellFormedString); // "Hello�World" (� replaces invalid surrogate)

7. ArrayBuffer Transfer

Transfer ownership dari ArrayBuffer:

const buffer1 = new ArrayBuffer(1024);
const view1 = new Uint8Array(buffer1);

// Fill with some data
view1[0] = 42;

// Transfer to new buffer
const buffer2 = buffer1.transfer();
const view2 = new Uint8Array(buffer2);

console.log(view2[0]); // 42
console.log(buffer1.byteLength); // 0 (transferred)
console.log(buffer2.byteLength); // 1024

Resize ArrayBuffer

const buffer = new ArrayBuffer(1024, { maxByteLength: 2048 });

// Resize to larger size
buffer.resize(1536);
console.log(buffer.byteLength); // 1536

// Transfer with different size
const newBuffer = buffer.transfer(512);
console.log(newBuffer.byteLength); // 512

8. RegExp v Flag

Enhanced Unicode support untuk regular expressions:

// Old way - limited Unicode support
const oldRegex = /[\u{1F600}-\u{1F64F}]/u;

// New way - better Unicode property support
const newRegex = /[\p{Emoji_Presentation}]/v;

const text = "Hello 😀 World 🌍";
console.log(text.match(newRegex)); // Better emoji matching

Browser Support dan Polyfills

Checking Support

// Check for Object.groupBy support
if (typeof Object.groupBy === 'function') {
  // Use native implementation
  const grouped = Object.groupBy(array, callback);
} else {
  // Use polyfill or fallback
  const grouped = customGroupBy(array, callback);
}

Simple Polyfill Example

// Simple Object.groupBy polyfill
if (!Object.groupBy) {
  Object.groupBy = function(array, callback) {
    const result = {};
    
    for (let i = 0; i < array.length; i++) {
      const key = callback(array[i], i);
      
      if (!result[key]) {
        result[key] = [];
      }
      
      result[key].push(array[i]);
    }
    
    return result;
  };
}

Best Practices

1. Progressive Enhancement

// Use feature detection
const groupData = (array, callback) => {
  if (Object.groupBy) {
    return Object.groupBy(array, callback);
  }
  
  // Fallback implementation
  return array.reduce((groups, item) => {
    const key = callback(item);
    groups[key] = groups[key] || [];
    groups[key].push(item);
    return groups;
  }, {});
};

2. TypeScript Support

// Type definitions for new features
interface ObjectConstructor {
  groupBy<T, K extends PropertyKey>(
    array: T[],
    callback: (item: T, index: number) => K
  ): Record<K, T[]>;
}

// Usage with types
const products: Product[] = [...];
const grouped: Record<string, Product[]> = Object.groupBy(
  products, 
  product => product.category
);

Kesimpulan

ES2024 membawa improvement yang signifikan untuk:

Yang Perlu Diingat

Selalu check browser compatibility sebelum menggunakan fitur baru di production

Next Steps

  1. Experiment dengan fitur-fitur ini di development environment
  2. Setup polyfills untuk browser compatibility
  3. Update TypeScript untuk type support
  4. Monitor browser support untuk adoption timeline

Stay updated dengan perkembangan JavaScript terbaru dengan mengikuti blog ini!