MCP HubMCP Hub
返回技能列表

modern-javascript-patterns

camoneart
更新于 Today
11 次查看
2
2
在 GitHub 上查看
ai

关于

This skill helps developers master ES6+ JavaScript features like async/await, destructuring, and functional programming patterns for writing clean, efficient code. It's ideal for refactoring legacy code, optimizing applications, and implementing modern asynchronous patterns. Use it to upgrade JavaScript syntax and adopt maintainable, performant coding practices.

技能文档

Modern JavaScript Patterns

Comprehensive guide for mastering modern JavaScript (ES6+) features, functional programming patterns, and best practices for writing clean, maintainable, and performant code.

When to Use This Skill

  • Refactoring legacy JavaScript to modern syntax
  • Implementing functional programming patterns
  • Optimizing JavaScript performance
  • Writing maintainable and readable code
  • Working with asynchronous operations
  • Building modern web applications
  • Migrating from callbacks to Promises/async-await
  • Implementing data transformation pipelines

ES6+ Core Features

1. Arrow Functions

Syntax and Use Cases:

// Traditional function
function add(a, b) {
  return a + b;
}

// Arrow function
const add = (a, b) => a + b;

// Single parameter (parentheses optional)
const double = x => x * 2;

// No parameters
const getRandom = () => Math.random();

// Multiple statements (need curly braces)
const processUser = user => {
  const normalized = user.name.toLowerCase();
  return { ...user, name: normalized };
};

// Returning objects (wrap in parentheses)
const createUser = (name, age) => ({ name, age });

Lexical 'this' Binding:

class Counter {
  constructor() {
    this.count = 0;
  }

  // Arrow function preserves 'this' context
  increment = () => {
    this.count++;
  };

  // Traditional function loses 'this' in callbacks
  incrementTraditional() {
    setTimeout(function() {
      this.count++;  // 'this' is undefined
    }, 1000);
  }

  // Arrow function maintains 'this'
  incrementArrow() {
    setTimeout(() => {
      this.count++;  // 'this' refers to Counter instance
    }, 1000);
  }
}

2. Destructuring

Object Destructuring:

const user = {
  id: 1,
  name: 'John Doe',
  email: '[email protected]',
  address: {
    city: 'New York',
    country: 'USA'
  }
};

// Basic destructuring
const { name, email } = user;

// Rename variables
const { name: userName, email: userEmail } = user;

// Default values
const { age = 25 } = user;

// Nested destructuring
const { address: { city, country } } = user;

// Rest operator
const { id, ...userWithoutId } = user;

// Function parameters
function greet({ name, age = 18 }) {
  console.log(`Hello ${name}, you are ${age}`);
}
greet(user);

Array Destructuring:

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

// Basic destructuring
const [first, second] = numbers;

// Skip elements
const [, , third] = numbers;

// Rest operator
const [head, ...tail] = numbers;

// Swapping variables
let a = 1, b = 2;
[a, b] = [b, a];

// Function return values
function getCoordinates() {
  return [10, 20];
}
const [x, y] = getCoordinates();

// Default values
const [one, two, three = 0] = [1, 2];

3. Spread and Rest Operators

Spread Operator:

// Array spreading
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2];

// Object spreading
const defaults = { theme: 'dark', lang: 'en' };
const userPrefs = { theme: 'light' };
const settings = { ...defaults, ...userPrefs };

// Function arguments
const numbers = [1, 2, 3];
Math.max(...numbers);

// Copying arrays/objects (shallow copy)
const copy = [...arr1];
const objCopy = { ...user };

// Adding items immutably
const newArr = [...arr1, 4, 5];
const newObj = { ...user, age: 30 };

Rest Parameters:

// Collect function arguments
function sum(...numbers) {
  return numbers.reduce((total, num) => total + num, 0);
}
sum(1, 2, 3, 4, 5);

// With regular parameters
function greet(greeting, ...names) {
  return `${greeting} ${names.join(', ')}`;
}
greet('Hello', 'John', 'Jane', 'Bob');

// Object rest
const { id, ...userData } = user;

// Array rest
const [first, ...rest] = [1, 2, 3, 4, 5];

4. Template Literals

// Basic usage
const name = 'John';
const greeting = `Hello, ${name}!`;

// Multi-line strings
const html = `
  <div>
    <h1>${title}</h1>
    <p>${content}</p>
  </div>
`;

// Expression evaluation
const price = 19.99;
const total = `Total: $${(price * 1.2).toFixed(2)}`;

// Tagged template literals
function highlight(strings, ...values) {
  return strings.reduce((result, str, i) => {
    const value = values[i] || '';
    return result + str + `<mark>${value}</mark>`;
  }, '');
}

const name = 'John';
const age = 30;
const html = highlight`Name: ${name}, Age: ${age}`;
// Output: "Name: <mark>John</mark>, Age: <mark>30</mark>"

5. Enhanced Object Literals

const name = 'John';
const age = 30;

// Shorthand property names
const user = { name, age };

// Shorthand method names
const calculator = {
  add(a, b) {
    return a + b;
  },
  subtract(a, b) {
    return a - b;
  }
};

// Computed property names
const field = 'email';
const user = {
  name: 'John',
  [field]: '[email protected]',
  [`get${field.charAt(0).toUpperCase()}${field.slice(1)}`]() {
    return this[field];
  }
};

// Dynamic property creation
const createUser = (name, ...props) => {
  return props.reduce((user, [key, value]) => ({
    ...user,
    [key]: value
  }), { name });
};

const user = createUser('John', ['age', 30], ['email', '[email protected]']);

Asynchronous Patterns

1. Promises

Creating and Using Promises:

// Creating a promise
const fetchUser = (id) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (id > 0) {
        resolve({ id, name: 'John' });
      } else {
        reject(new Error('Invalid ID'));
      }
    }, 1000);
  });
};

// Using promises
fetchUser(1)
  .then(user => console.log(user))
  .catch(error => console.error(error))
  .finally(() => console.log('Done'));

// Chaining promises
fetchUser(1)
  .then(user => fetchUserPosts(user.id))
  .then(posts => processPosts(posts))
  .then(result => console.log(result))
  .catch(error => console.error(error));

Promise Combinators:

// Promise.all - Wait for all promises
const promises = [
  fetchUser(1),
  fetchUser(2),
  fetchUser(3)
];

Promise.all(promises)
  .then(users => console.log(users))
  .catch(error => console.error('At least one failed:', error));

// Promise.allSettled - Wait for all, regardless of outcome
Promise.allSettled(promises)
  .then(results => {
    results.forEach(result => {
      if (result.status === 'fulfilled') {
        console.log('Success:', result.value);
      } else {
        console.log('Error:', result.reason);
      }
    });
  });

// Promise.race - First to complete
Promise.race(promises)
  .then(winner => console.log('First:', winner))
  .catch(error => console.error(error));

// Promise.any - First to succeed
Promise.any(promises)
  .then(first => console.log('First success:', first))
  .catch(error => console.error('All failed:', error));

2. Async/Await

Basic Usage:

// Async function always returns a Promise
async function fetchUser(id) {
  const response = await fetch(`/api/users/${id}`);
  const user = await response.json();
  return user;
}

// Error handling with try/catch
async function getUserData(id) {
  try {
    const user = await fetchUser(id);
    const posts = await fetchUserPosts(user.id);
    return { user, posts };
  } catch (error) {
    console.error('Error fetching data:', error);
    throw error;
  }
}

// Sequential vs Parallel execution
async function sequential() {
  const user1 = await fetchUser(1);  // Wait
  const user2 = await fetchUser(2);  // Then wait
  return [user1, user2];
}

async function parallel() {
  const [user1, user2] = await Promise.all([
    fetchUser(1),
    fetchUser(2)
  ]);
  return [user1, user2];
}

Advanced Patterns:

// Async IIFE
(async () => {
  const result = await someAsyncOperation();
  console.log(result);
})();

// Async iteration
async function processUsers(userIds) {
  for (const id of userIds) {
    const user = await fetchUser(id);
    await processUser(user);
  }
}

// Top-level await (ES2022)
const config = await fetch('/config.json').then(r => r.json());

// Retry logic
async function fetchWithRetry(url, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      return await fetch(url);
    } catch (error) {
      if (i === retries - 1) throw error;
      await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
    }
  }
}

// Timeout wrapper
async function withTimeout(promise, ms) {
  const timeout = new Promise((_, reject) =>
    setTimeout(() => reject(new Error('Timeout')), ms)
  );
  return Promise.race([promise, timeout]);
}

Functional Programming Patterns

1. Array Methods

Map, Filter, Reduce:

const users = [
  { id: 1, name: 'John', age: 30, active: true },
  { id: 2, name: 'Jane', age: 25, active: false },
  { id: 3, name: 'Bob', age: 35, active: true }
];

// Map - Transform array
const names = users.map(user => user.name);
const upperNames = users.map(user => user.name.toUpperCase());

// Filter - Select elements
const activeUsers = users.filter(user => user.active);
const adults = users.filter(user => user.age >= 18);

// Reduce - Aggregate data
const totalAge = users.reduce((sum, user) => sum + user.age, 0);
const avgAge = totalAge / users.length;

// Group by property
const byActive = users.reduce((groups, user) => {
  const key = user.active ? 'active' : 'inactive';
  return {
    ...groups,
    [key]: [...(groups[key] || []), user]
  };
}, {});

// Chaining methods
const result = users
  .filter(user => user.active)
  .map(user => user.name)
  .sort()
  .join(', ');

Advanced Array Methods:

// Find - First matching element
const user = users.find(u => u.id === 2);

// FindIndex - Index of first match
const index = users.findIndex(u => u.name === 'Jane');

// Some - At least one matches
const hasActive = users.some(u => u.active);

// Every - All match
const allAdults = users.every(u => u.age >= 18);

// FlatMap - Map and flatten
const userTags = [
  { name: 'John', tags: ['admin', 'user'] },
  { name: 'Jane', tags: ['user'] }
];
const allTags = userTags.flatMap(u => u.tags);

// From - Create array from iterable
const str = 'hello';
const chars = Array.from(str);
const numbers = Array.from({ length: 5 }, (_, i) => i + 1);

// Of - Create array from arguments
const arr = Array.of(1, 2, 3);

2. Higher-Order Functions

Functions as Arguments:

// Custom forEach
function forEach(array, callback) {
  for (let i = 0; i < array.length; i++) {
    callback(array[i], i, array);
  }
}

// Custom map
function map(array, transform) {
  const result = [];
  for (const item of array) {
    result.push(transform(item));
  }
  return result;
}

// Custom filter
function filter(array, predicate) {
  const result = [];
  for (const item of array) {
    if (predicate(item)) {
      result.push(item);
    }
  }
  return result;
}

Functions Returning Functions:

// Currying
const multiply = a => b => a * b;
const double = multiply(2);
const triple = multiply(3);

console.log(double(5));  // 10
console.log(triple(5));  // 15

// Partial application
function partial(fn, ...args) {
  return (...moreArgs) => fn(...args, ...moreArgs);
}

const add = (a, b, c) => a + b + c;
const add5 = partial(add, 5);
console.log(add5(3, 2));  // 10

// Memoization
function memoize(fn) {
  const cache = new Map();
  return (...args) => {
    const key = JSON.stringify(args);
    if (cache.has(key)) {
      return cache.get(key);
    }
    const result = fn(...args);
    cache.set(key, result);
    return result;
  };
}

const fibonacci = memoize((n) => {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
});

3. Composition and Piping

// Function composition
const compose = (...fns) => x =>
  fns.reduceRight((acc, fn) => fn(acc), x);

const pipe = (...fns) => x =>
  fns.reduce((acc, fn) => fn(acc), x);

// Example usage
const addOne = x => x + 1;
const double = x => x * 2;
const square = x => x * x;

const composed = compose(square, double, addOne);
console.log(composed(3));  // ((3 + 1) * 2)^2 = 64

const piped = pipe(addOne, double, square);
console.log(piped(3));  // ((3 + 1) * 2)^2 = 64

// Practical example
const processUser = pipe(
  user => ({ ...user, name: user.name.trim() }),
  user => ({ ...user, email: user.email.toLowerCase() }),
  user => ({ ...user, age: parseInt(user.age) })
);

const user = processUser({
  name: '  John  ',
  email: '[email protected]',
  age: '30'
});

4. Pure Functions and Immutability

// Impure function (modifies input)
function addItemImpure(cart, item) {
  cart.items.push(item);
  cart.total += item.price;
  return cart;
}

// Pure function (no side effects)
function addItemPure(cart, item) {
  return {
    ...cart,
    items: [...cart.items, item],
    total: cart.total + item.price
  };
}

// Immutable array operations
const numbers = [1, 2, 3, 4, 5];

// Add to array
const withSix = [...numbers, 6];

// Remove from array
const withoutThree = numbers.filter(n => n !== 3);

// Update array element
const doubled = numbers.map(n => n === 3 ? n * 2 : n);

// Immutable object operations
const user = { name: 'John', age: 30 };

// Update property
const olderUser = { ...user, age: 31 };

// Add property
const withEmail = { ...user, email: '[email protected]' };

// Remove property
const { age, ...withoutAge } = user;

// Deep cloning (simple approach)
const deepClone = obj => JSON.parse(JSON.stringify(obj));

// Better deep cloning
const structuredClone = obj => globalThis.structuredClone(obj);

Modern Class Features

// Class syntax
class User {
  // Private fields
  #password;

  // Public fields
  id;
  name;

  // Static field
  static count = 0;

  constructor(id, name, password) {
    this.id = id;
    this.name = name;
    this.#password = password;
    User.count++;
  }

  // Public method
  greet() {
    return `Hello, ${this.name}`;
  }

  // Private method
  #hashPassword(password) {
    return `hashed_${password}`;
  }

  // Getter
  get displayName() {
    return this.name.toUpperCase();
  }

  // Setter
  set password(newPassword) {
    this.#password = this.#hashPassword(newPassword);
  }

  // Static method
  static create(id, name, password) {
    return new User(id, name, password);
  }
}

// Inheritance
class Admin extends User {
  constructor(id, name, password, role) {
    super(id, name, password);
    this.role = role;
  }

  greet() {
    return `${super.greet()}, I'm an admin`;
  }
}

Modules (ES6)

// Exporting
// math.js
export const PI = 3.14159;
export function add(a, b) {
  return a + b;
}
export class Calculator {
  // ...
}

// Default export
export default function multiply(a, b) {
  return a * b;
}

// Importing
// app.js
import multiply, { PI, add, Calculator } from './math.js';

// Rename imports
import { add as sum } from './math.js';

// Import all
import * as Math from './math.js';

// Dynamic imports
const module = await import('./math.js');
const { add } = await import('./math.js');

// Conditional loading
if (condition) {
  const module = await import('./feature.js');
  module.init();
}

Iterators and Generators

// Custom iterator
const range = {
  from: 1,
  to: 5,

  [Symbol.iterator]() {
    return {
      current: this.from,
      last: this.to,

      next() {
        if (this.current <= this.last) {
          return { done: false, value: this.current++ };
        } else {
          return { done: true };
        }
      }
    };
  }
};

for (const num of range) {
  console.log(num);  // 1, 2, 3, 4, 5
}

// Generator function
function* rangeGenerator(from, to) {
  for (let i = from; i <= to; i++) {
    yield i;
  }
}

for (const num of rangeGenerator(1, 5)) {
  console.log(num);
}

// Infinite generator
function* fibonacci() {
  let [prev, curr] = [0, 1];
  while (true) {
    yield curr;
    [prev, curr] = [curr, prev + curr];
  }
}

// Async generator
async function* fetchPages(url) {
  let page = 1;
  while (true) {
    const response = await fetch(`${url}?page=${page}`);
    const data = await response.json();
    if (data.length === 0) break;
    yield data;
    page++;
  }
}

for await (const page of fetchPages('/api/users')) {
  console.log(page);
}

Modern Operators

// Optional chaining
const user = { name: 'John', address: { city: 'NYC' } };
const city = user?.address?.city;
const zipCode = user?.address?.zipCode;  // undefined

// Function call
const result = obj.method?.();

// Array access
const first = arr?.[0];

// Nullish coalescing
const value = null ?? 'default';      // 'default'
const value = undefined ?? 'default'; // 'default'
const value = 0 ?? 'default';         // 0 (not 'default')
const value = '' ?? 'default';        // '' (not 'default')

// Logical assignment
let a = null;
a ??= 'default';  // a = 'default'

let b = 5;
b ??= 10;  // b = 5 (unchanged)

let obj = { count: 0 };
obj.count ||= 1;  // obj.count = 1
obj.count &&= 2;  // obj.count = 2

Performance Optimization

// Debounce
function debounce(fn, delay) {
  let timeoutId;
  return (...args) => {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => fn(...args), delay);
  };
}

const searchDebounced = debounce(search, 300);

// Throttle
function throttle(fn, limit) {
  let inThrottle;
  return (...args) => {
    if (!inThrottle) {
      fn(...args);
      inThrottle = true;
      setTimeout(() => inThrottle = false, limit);
    }
  };
}

const scrollThrottled = throttle(handleScroll, 100);

// Lazy evaluation
function* lazyMap(iterable, transform) {
  for (const item of iterable) {
    yield transform(item);
  }
}

// Use only what you need
const numbers = [1, 2, 3, 4, 5];
const doubled = lazyMap(numbers, x => x * 2);
const first = doubled.next().value;  // Only computes first value

Best Practices

  1. Use const by default: Only use let when reassignment is needed
  2. Prefer arrow functions: Especially for callbacks
  3. Use template literals: Instead of string concatenation
  4. Destructure objects and arrays: For cleaner code
  5. Use async/await: Instead of Promise chains
  6. Avoid mutating data: Use spread operator and array methods
  7. Use optional chaining: Prevent "Cannot read property of undefined"
  8. Use nullish coalescing: For default values
  9. Prefer array methods: Over traditional loops
  10. Use modules: For better code organization
  11. Write pure functions: Easier to test and reason about
  12. Use meaningful variable names: Self-documenting code
  13. Keep functions small: Single responsibility principle
  14. Handle errors properly: Use try/catch with async/await
  15. Use strict mode: 'use strict' for better error catching

Common Pitfalls

  1. this binding confusion: Use arrow functions or bind()
  2. Async/await without error handling: Always use try/catch
  3. Promise creation unnecessary: Don't wrap already async functions
  4. Mutation of objects: Use spread operator or Object.assign()
  5. Forgetting await: Async functions return promises
  6. Blocking event loop: Avoid synchronous operations
  7. Memory leaks: Clean up event listeners and timers
  8. Not handling promise rejections: Use catch() or try/catch

Resources

快速安装

/plugin add https://github.com/camoneart/claude-code/tree/main/modern-javascript-patterns

在 Claude Code 中复制并粘贴此命令以安装该技能

GitHub 仓库

camoneart/claude-code
路径: skills/modern-javascript-patterns

相关推荐技能

llamaguard

其他

LlamaGuard是Meta推出的7-8B参数内容审核模型,专门用于过滤LLM的输入和输出内容。它能检测六大安全风险类别(暴力/仇恨、性内容、武器、违禁品、自残、犯罪计划),准确率达94-95%。开发者可通过HuggingFace、vLLM或Sagemaker快速部署,并能与NeMo Guardrails集成实现自动化安全防护。

查看技能

sglang

SGLang是一个专为LLM设计的高性能推理框架,特别适用于需要结构化输出的场景。它通过RadixAttention前缀缓存技术,在处理JSON、正则表达式、工具调用等具有重复前缀的复杂工作流时,能实现极速生成。如果你正在构建智能体或多轮对话系统,并追求远超vLLM的推理性能,SGLang是理想选择。

查看技能

evaluating-llms-harness

测试

该Skill通过60+个学术基准测试(如MMLU、GSM8K等)评估大语言模型质量,适用于模型对比、学术研究及训练进度追踪。它支持HuggingFace、vLLM和API接口,被EleutherAI等行业领先机构广泛采用。开发者可通过简单命令行快速对模型进行多任务批量评估。

查看技能

langchain

LangChain是一个用于构建LLM应用程序的框架,支持智能体、链和RAG应用开发。它提供多模型提供商支持、500+工具集成、记忆管理和向量检索等核心功能。开发者可用它快速构建聊天机器人、问答系统和自主代理,适用于从原型验证到生产部署的全流程。

查看技能