Install any skill in seconds. Free to start, no credit card required.
Get Started Free →A comprehensive JavaScript style guide skill. When activated, it provides best-practice JavaScript coding conventions and generates code that strictly follows the style guide, covering variables, functions, objects, arrays, classes, modules, async patterns, error handling, naming conventions, and more.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-03 | ✗→✓ | ▲ Improved | 148% | 0% |
| case-01 | ✗→✓ | ▲ Improved | 185% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 453% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 327% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 716% | 0% |
This skill activates when the user mentions or implies JavaScript in their request. Once activated, it:
const for all references; avoid var.let instead of var.const and let are block-scoped, whereas var is function-scoped.javascript// bad var count = 1; // good const count = 1; let mutableValue = 1; mutableValue += 1;
...) over Object.assign to shallow-copy objects.javascript// bad const item = new Object(); // good const item = {}; // computed property names const key = 'name'; const obj = { [key]: 'value' }; // method & property shorthand const name = 'Alice'; const atom = { name, value: 1, addValue(val) { return atom.value + val; }, }; // shallow copy const original = { a: 1, b: 2 }; const copy = { ...original, c: 3 };
Array.from or the spread operator to convert array-like objects.return statements in array method callbacks.javascript// bad const items = new Array(); // good const items = []; // convert iterable const nodes = Array.from(document.querySelectorAll('.item')); const uniqueValues = [...new Set(arr)]; // array methods [1, 2, 3].map((x) => x + 1); [1, 2, 3].map((x) => { const y = x + 1; return x * y; });
javascript// bad function getFullName(user) { const firstName = user.firstName; const lastName = user.lastName; return `${firstName} ${lastName}`; } // good function getFullName({ firstName, lastName }) { return `${firstName} ${lastName}`; } // array destructuring const [first, , third] = [1, 2, 3]; // multiple return values — use object destructuring function processInput(input) { return { left, right, top, bottom }; } const { left, top } = processInput(input);
'' for strings.eval() on a string.javascript// bad const name = "Alice"; const greeting = 'Hello, ' + name + '!'; // good const name = 'Alice'; const greeting = `Hello, ${name}!`;
if, while, etc.).arguments.Function constructor to create a new function.... to call variadic functions....args) instead of arguments.javascript// named function expression const short = function longUniqueMoreDescriptiveLexicalFoo() { // ... }; // default parameters last function handleThings(name, opts = {}) { // ... } // rest parameters function concatenateAll(...args) { return args.join(''); } // spread to call const values = [1, 2, 3]; console.log(Math.max(...values));
javascript// bad [1, 2, 3].map(function (x) { const y = x + 1; return x * y; }); // good [1, 2, 3].map((x) => { const y = x + 1; return x * y; }); // implicit return [1, 2, 3].map((x) => x * 2); // multiline implicit return [1, 2, 3].map((number) => ( `A long string with the ${number}. It's so long that we don't want it to take up space on the .map line!` ));
class; avoid manipulating prototype directly.extends for inheritance.this to enable method chaining.javascript// bad function Queue(contents = []) { this.queue = [...contents]; } Queue.prototype.pop = function () { return this.queue.pop(); }; // good class Queue { constructor(contents = []) { this.queue = [...contents]; } pop() { return this.queue.pop(); } } // inheritance class PeekableQueue extends Queue { peek() { return this.queue[0]; } }
import/export) over a non-standard module system.imports above non-import statements.javascript// bad const utils = require('./utils'); module.exports = utils.fetchData; // good import { fetchData } from './utils'; export default fetchData; // single place import import { named1, named2 } from 'module'; // multiline import { longNameA, longNameB, longNameC, } from 'path/to/module';
for-in or for-of loops.map, filter, reduce, find, findIndex, every, some, etc.javascriptconst numbers = [1, 2, 3, 4, 5]; // bad let sum = 0; for (const num of numbers) { sum += num; } // good const sum = numbers.reduce((total, num) => total + num, 0); // filtering const evens = numbers.filter((num) => num % 2 === 0);
[] when accessing properties with a variable.** instead of Math.pow.javascriptconst luke = { jedi: true, age: 28 }; // dot notation const isJedi = luke.jedi; // bracket notation const prop = 'jedi'; const isJedi = luke[prop]; // exponentiation const result = 2 ** 10;
const or let; never use var.const or let declaration per variable or assignment.consts and then group all lets.++, --); use += 1 / -= 1 instead.= in an assignment.javascript// bad const items = getItems(), goSportsTeam = true, dragonball = 'z'; // good const items = getItems(); const goSportsTeam = true; const dragonball = 'z'; // group const then let const a = 1; const b = 2; let c = 3; let d = 4; // avoid unary let count = 0; count += 1;
var declarations get hoisted; const and let are in Temporal Dead Zone.=== and !== over == and !=.case and default clauses that contain lexical declarations.**, +, -).javascript// bad if (isValid == true) { /* ... */ } if (name != '') { /* ... */ } // good if (isValid) { /* ... */ } if (name !== '') { /* ... */ } if (collection.length > 0) { /* ... */ } // no nested ternaries const thing = foo === 123 ? bar : foobar;
else on the same line as the if block's closing brace.if block always executes a return, the subsequent else block is unnecessary.javascript// bad if (test) return false; // good if (test) return false; if (test) { return false; } // if/else if (test) { thing1(); } else { thing2(); }
if, while, etc.) gets too long, each grouped condition should be on a new line, with the logical operator at the beginning of the line.javascriptif ( foo === 123 && bar === 'abc' ) { thing1(); }
/** ... */ for multiline comments.// for single-line comments. Place them on a new line above the subject.FIXME: or TODO: to annotate problems or suggest actions.javascript// good single line // This is a comment const active = true; /** * Multiline comment explaining the function. * @param {string} tag - The tag name. * @returns {Element} The created element. */ function make(tag) { return document.createElement(tag); } // TODO: implement caching // FIXME: should not use global state
javascript// bad function foo(){ const name='Alice'; } // good function foo() { const name = 'Alice'; } // method chaining $('#items') .find('.selected') .highlight() .end() .find('.open') .updateCount();
javascript// bad — leading commas const hero = { firstName: 'Ada' , lastName: 'Lovelace' }; // good — trailing commas const hero = { firstName: 'Ada', lastName: 'Lovelace', }; const heroes = [ 'Batman', 'Superman', ];
javascript// bad const name = 'Alice' // good const name = 'Alice';
String() for strings, Number() for numbers, Boolean() or !! for booleans.parseInt always with a radix.javascriptconst val = '4'; // bad const totalScore = val + 0; // good const totalScore = Number(val); const inputValue = String(someNum); const hasAge = Boolean(age); const hasName = !!name; const count = parseInt(inputValue, 10);
javascript// bad const OBJEcttsssss = {}; function c() {} const u = new user(); // good const thisIsMyObject = {}; function calculateTotal() {} const user = new User(); // constants export const API_BASE_URL = 'https://api.example.com'; export const MAX_RETRY_COUNT = 3; // filename examples // file: makeStyleGuide.js → export default function makeStyleGuide() {} // file: User.js → export default class User {}
getVal() and setVal('value').isVal() or hasVal().javascript// bad dragon.age(); // good dragon.getAge(); dragon.setAge(25); dragon.isAlive(); dragon.hasWings();
javascript// bad emitter.emit('itemUpdate', item.id); // good emitter.emit('itemUpdate', { itemId: item.id });
async/await over chaining .then() and .catch().try...catch in async functions.Promise.all for concurrent independent async operations.Promise.allSettled when you need results of all promises regardless of rejection.javascript// bad function fetchData() { return getData() .then((data) => parseData(data)) .then((parsed) => validate(parsed)) .catch((err) => console.error(err)); } // good async function fetchData() { try { const data = await getData(); const parsed = await parseData(data); return validate(parsed); } catch (err) { console.error(err); throw err; } } // concurrent operations async function loadDashboard() { const [user, posts, notifications] = await Promise.all([ fetchUser(), fetchPosts(), fetchNotifications(), ]); return { user, posts, notifications }; }
Error objects (or subclasses of Error).javascript// bad throw 'Something went wrong'; throw { message: 'error' }; // good throw new Error('Something went wrong'); class ValidationError extends Error { constructor(message, field) { super(message); this.name = 'ValidationError'; this.field = field; } } throw new ValidationError('Invalid email', 'email');
?.) to access nested properties that may not exist.??) instead of || when you want to allow falsy values like 0 or ''.javascript// bad const city = user && user.address && user.address.city; const port = config.port || 3000; // breaks if port is 0 // good const city = user?.address?.city; const port = config.port ?? 3000;
Number.isNaN instead of global isNaN.Number.isFinite instead of global isFinite.javascript// bad isNaN('1.2'); isFinite('2e3'); // good Number.isNaN('1.2'); Number.isFinite('2e3');
This is a Prompt-based Skill (natural language activation).
"How should I write a JavaScript function that fetches user data?"
"Review this JavaScript code for style issues: [paste code]"
"Write a JavaScript module to handle form validation"
"What's the correct way to declare variables in JavaScript?" "How should I handle async errors in JavaScript?"
User: Write a JavaScript utility function to deep clone an object.
Skill Response: Generates clean, style-guide-compliant code:
javascript/** * Deep clones a plain object or array using structured cloning. * Falls back to JSON serialization for environments without structuredClone. * * @param {Object|Array} source - The value to clone. * @returns {Object|Array} A deep copy of the source. */ function deepClone(source) { if (typeof structuredClone === 'function') { return structuredClone(source); } return JSON.parse(JSON.stringify(source)); } export default deepClone;
Other measured skills in the registry, with their headline benchmark lift.