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.// bad
var count = 1;
// good
const count = 1;
let mutableValue = 1;
mutableValue += 1;
...) over Object.assign to shallow-copy objects.// 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.// 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;
});
// 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.// 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.// 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));
// 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.// 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.// 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.const 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.const 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.// 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.**, +, -).// 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.// 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.if (
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.// 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
// bad
function foo(){
const name='Alice';
}
// good
function foo() {
const name = 'Alice';
}
// method chaining
$('#items')
.find('.selected')
.highlight()
.end()
.find('.open')
.updateCount();
// bad — leading commas
const hero = {
firstName: 'Ada'
, lastName: 'Lovelace'
};
// good — trailing commas
const hero = {
firstName: 'Ada',
lastName: 'Lovelace',
};
const heroes = [
'Batman',
'Superman',
];
// bad
const name = 'Alice'
// good
const name = 'Alice';
String() for strings, Number() for numbers, Boolean() or !! for booleans.parseInt always with a radix.const 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);
// 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().// bad
dragon.age();
// good
dragon.getAge();
dragon.setAge(25);
dragon.isAlive();
dragon.hasWings();
// 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.// 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).// 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 ''.// 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.// 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:
/**
* 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;
共 1 个版本