‹ 首页

standards-javascript

@b33eep · 收录于 1 周前

This skill provides JavaScript coding standards and is automatically loaded for JavaScript projects. It includes modern ES2025 patterns, async handling, and recommended tooling.

适合你,如果你在写 JavaScript 项目并希望统一代码风格。

/ 下载安装
standards-javascript.skill双击,或拖进 Claude 桌面版 / Cowork,即完成安装↓ .skill↓ .zip
用别的 agent?下载 .zip 解压,把文件夹放进它的技能目录
Claude Code~/.claude/skills/(项目级 .claude/skills/)
Codex CLI~/.codex/skills/
Cursor自动读取上面两处目录
其他工具见其文档的「skills」目录;两个下载是同一份文件,只是名字不同
/ 通过 npx 安装 校验哈希
npx oh-my-skill add b33eep/claude-code-setup/standards-javascript
/ 通过 bash 安装
curl -fsSL https://oh-my-skill.com/install.sh | bash -s -- b33eep/claude-code-setup/standards-javascript
/ 已经装过?验证本机副本,不用重装
npx oh-my-skill verify b33eep/claude-code-setup/standards-javascript
安装目标可用 --agent / --scope 或 --to 明确指定;省略时只会在唯一已存在的 agent 目录上自动选择,零命中或多命中会停止并提示。content_hash 缺失或不一致均拒装。
56GitHub stars
~2.1K上下文体积 · 单文件
镜像托管

怎么用

技能原文 SKILL.md作者撰写 · MIT · 7e8cc42

JavaScript Coding Standards

Core Principles
  1. Simplicity: Simple, understandable code
  2. Readability: Readability over cleverness
  3. Maintainability: Code that's easy to maintain
  4. Testability: Code that's easy to test
  5. DRY: Don't Repeat Yourself - but don't overdo it
General Rules
  • Early Returns: Use early returns to avoid nesting
  • Descriptive Names: Meaningful names for variables and functions
  • Minimal Changes: Only change relevant code parts
  • No Over-Engineering: No unnecessary complexity
  • Minimal Comments: Code should be self-explanatory. No redundant comments!
  • Async/Await: Always use async/await for async operations
Naming Conventions

| Element | Convention | Example | |---------|------------|---------| | Variables/Functions | camelCase | getUserById, isActive | | Classes | PascalCase | UserService, ApiClient | | Constants | UPPER_SNAKE_CASE | MAX_RETRY_COUNT | | Private | Prefix with _ or # | _internalMethod, #privateField | | Files | kebab-case or camelCase | user-service.js, userService.js | | Event Handlers | Prefix with handle | handleClick, handleSubmit |

Project Structure
myproject/
├── src/
│   ├── index.js              # Entry point
│   ├── config.js             # Settings, env vars
│   ├── models/
│   │   └── user.js           # Domain models
│   ├── services/
│   │   └── user-service.js   # Business logic
│   ├── routes/
│   │   └── user-routes.js    # API routes
│   └── utils/
│       └── helpers.js        # Utility functions
├── tests/
│   ├── services/
│   │   └── user-service.test.js
│   └── setup.js
├── package.json
└── README.md
ES Modules (Preferred)
// math.js - Named exports
export function add(a, b) {
    return a + b;
}

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

// app.js - Import
import { add, multiply } from './math.js';

// Default export
export default class UserService {
    // ...
}

// Import default
import UserService from './user-service.js';

package.json for ES Modules:

{
    "type": "module",
    "exports": {
        ".": "./src/index.js",
        "./utils": "./src/utils/index.js"
    }
}
Async/Await Patterns
// Always use async/await for async operations
async function fetchUserData(userId) {
    try {
        const response = await fetch(`https://api.example.com/users/${userId}`);

        if (!response.ok) {
            throw new Error(`API error: ${response.statusText}`);
        }

        return await response.json();
    } catch (error) {
        console.error('Fetch failed:', error);
        throw error;
    }
}

// Parallel execution with Promise.all
async function fetchMultipleUsers(userIds) {
    const users = await Promise.all(
        userIds.map(id => fetchUserData(id))
    );
    return users;
}

// Race with timeout
async function fetchWithTimeout(promise, timeout) {
    return Promise.race([
        promise,
        new Promise((_, reject) =>
            setTimeout(() => reject(new Error('Timeout')), timeout)
        ),
    ]);
}

// Get all results, including failures
async function fetchAllSettled(urls) {
    const results = await Promise.allSettled(
        urls.map(url => fetch(url).then(r => r.json()))
    );
    return results;
}
Best Practices
// Prefer const over let
const users = [];

// Use nullish coalescing and optional chaining
const name = user?.profile?.name ?? 'Anonymous';

// Prefer template literals
const message = `Hello, ${user.name}!`;

// Use destructuring
const { id, name, email } = user;
function processUser({ id, name }) { }

// Prefer array methods over loops
const activeUsers = users.filter(u => u.isActive);
const userNames = users.map(u => u.name);
const totalAge = users.reduce((sum, u) => sum + u.age, 0);

// Use Object.freeze for immutable constants
const CONFIG = Object.freeze({
    apiUrl: 'https://api.example.com',
    maxRetries: 3,
});

// Private class fields with #
class UserService {
    #apiClient;

    constructor(apiClient) {
        this.#apiClient = apiClient;
    }

    async getUser(id) {
        return this.#apiClient.get(`/users/${id}`);
    }
}
Express Framework
import express from 'express';

const app = express();
app.use(express.json());

// Routes
app.get('/users', (req, res) => {
    res.json([
        { id: 1, name: 'John' },
        { id: 2, name: 'Jane' },
    ]);
});

app.post('/users', (req, res) => {
    const { name } = req.body;
    res.status(201).json({ id: 3, name });
});

app.get('/users/:id', (req, res) => {
    const { id } = req.params;
    res.json({ id: parseInt(id), name: 'User' });
});

// Error handling middleware (must be last)
app.use((err, req, res, next) => {
    console.error(err.stack);
    res.status(500).json({ error: 'Internal Server Error' });
});

app.listen(3000, () => {
    console.log('Server running on :3000');
});

Middleware Pattern:

// Logging middleware
const logger = (req, res, next) => {
    console.log(`${req.method} ${req.path}`);
    next();
};

// Authentication middleware
const authenticateToken = (req, res, next) => {
    const authHeader = req.headers['authorization'];
    const token = authHeader?.split(' ')[1];

    if (!token) {
        return res.status(401).json({ error: 'Missing token' });
    }

    // Verify token...
    req.user = decodedUser;
    next();
};

app.use(logger);
app.use('/api/protected', authenticateToken);
Fastify Framework
import Fastify from 'fastify';

const fastify = Fastify({ logger: true });

fastify.get('/users/:id', async (request, reply) => {
    const { id } = request.params;
    return { id: parseInt(id), name: 'User' };
});

fastify.post('/users', async (request, reply) => {
    const { name } = request.body;
    reply.code(201);
    return { id: 1, name };
});

fastify.listen({ port: 3000 }, (err, address) => {
    if (err) throw err;
    console.log(`Server listening at ${address}`);
});
Error Handling
// Custom error classes
class AppError extends Error {
    constructor(message, statusCode = 500) {
        super(message);
        this.name = 'AppError';
        this.statusCode = statusCode;
    }
}

class NotFoundError extends AppError {
    constructor(resource) {
        super(`${resource} not found`, 404);
        this.name = 'NotFoundError';
    }
}

// Result pattern for explicit error handling
function divide(a, b) {
    if (b === 0) {
        return { ok: false, error: 'Division by zero' };
    }
    return { ok: true, value: a / b };
}

const result = divide(10, 2);
if (result.ok) {
    console.log(result.value);
} else {
    console.error(result.error);
}
Testing with Vitest
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { add, multiply } from './math.js';

describe('Math utils', () => {
    it('should add numbers', () => {
        expect(add(2, 3)).toBe(5);
    });

    it('should multiply numbers', () => {
        expect(multiply(2, 3)).toBe(6);
    });
});

// Integration test example
describe('API Endpoints', () => {
    let server;

    beforeEach(() => {
        server = createServer();
    });

    afterEach(() => {
        server.close();
    });

    it('GET /users returns user list', async () => {
        const response = await fetch('http://localhost:3000/users');
        const data = await response.json();

        expect(response.ok).toBe(true);
        expect(Array.isArray(data)).toBe(true);
    });
});
Environment Configuration
// config.js
const config = {
    development: {
        port: 3000,
        database: 'mongodb://localhost:27017/mydb',
        logLevel: 'debug',
    },
    production: {
        port: process.env.PORT || 8080,
        database: process.env.DATABASE_URL,
        logLevel: 'info',
    },
};

const env = process.env.NODE_ENV || 'development';
export default config[env];
Comments - Less is More
// BAD - redundant comment
// Get the user from database
const user = repository.getUser(userId);

// GOOD - self-explanatory code, no comment needed
const user = repository.getUser(userId);

// GOOD - comment explains WHY (not obvious)
// Rate limit: API allows max 1000 requests/min
await rateLimiter.acquire();
Recommended Tooling

| Tool | Purpose | |------|---------| | pnpm or bun | Package manager (faster than npm) | | eslint | Linting | | prettier | Code formatting | | vitest or jest | Testing framework | | node --watch | Development with auto-reload | | dotenv | Environment variable management |

package.json Template
{
    "name": "@org/myapp",
    "version": "1.0.0",
    "type": "module",
    "main": "src/index.js",
    "exports": {
        ".": "./src/index.js",
        "./utils": "./src/utils/index.js"
    },
    "engines": {
        "node": ">=22.0.0"
    },
    "scripts": {
        "dev": "node --watch src/index.js",
        "start": "node src/index.js",
        "test": "vitest",
        "lint": "eslint ."
    }
}
Production Best Practices
  1. ES Modules - Use "type": "module" in package.json
  2. Async/Await - Always use async/await for async operations
  3. Error Handling - Handle promise rejections properly
  4. Validation - Validate input in API endpoints
  5. Environment Variables - Use dotenv or similar for config
  6. Graceful Shutdown - Handle SIGTERM for clean exit
  7. Testing - Test with Vitest or Jest
  8. Linting - Use ESLint with recommended rules
  9. Security - Run npm audit regularly
  10. Process Management - Use PM2 for production

References
按 MIT 许可原样转载,未经改动 · 在 GitHub 查看 →

评论

登录即可评论;带「已验证安装」的,是发布者名下有本店的安装或持有记录。