用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/Objective-Arts/lens-dist --skill functional命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
基于 SOC 职业分类
| name | functional |
| description | Functional JS elegance |
Applying the design philosophy of Jeremy Ashkenas (Backbone.js, Underscore.js, CoffeeScript) to JavaScript library and utility development. Use this when writing JavaScript utilities, designing APIs, building small libraries, or refactoring code toward functional elegance. Auto-invokes for .js files involving utility functions, library design, collection manipulation, or API surface design. Not for framework-heavy code (React, Angular), build tooling, or Node.js server infrastructure.
Readable over clever. Code is read far more than written. Optimize for the reader who encounters your code six months from now.
Small, focused functions. Each function does one thing. Name it for what it does. If the name is awkward, the function does too much.
Functional foundations. Prefer map, filter, reduce over loops. Treat data as immutable. Return new values rather than mutating.
Minimal API surface. The best library is the smallest one that solves the problem. Every public method is a promise to maintain.
Convention over configuration. Establish sensible defaults. Let users override when needed, not require configuration upfront.
// Transform collections, not items
const getActiveUserEmails = (users) =>
users
.filter(user => user.active)
.map(user => user.email);
// Not this - imperative, mutable
const getActiveUserEmails = (users) => {
const emails = [];
for (let i = 0; i < users.length; i++) {
if (users[i].active) {
emails.push(users[i].email);
}
}
return emails;
};
// Loose coupling through events
class Model {
constructor() {
this._events = {};
this._attributes = {};
}
set(key, value) {
const prev = this._attributes[key];
this._attributes[key] = value;
if (prev !== value) {
this.trigger('change', key, value, prev);
this.trigger(`change:${key}`, value, prev);
}
return this;
}
on(event, callback) {
(this._events[event] ||= []).push(callback);
return this;
}
trigger(event, ...args) {
(this._events[event] || []).forEach(cb => cb(...args));
return this;
}
}
// Everything returns a value
const classify = (score) =>
score >= 90 ? 'A' :
score >= 80 ? 'B' :
score >= 70 ? 'C' :
score >= 60 ? 'D' : 'F';
// Destructuring for clarity
const formatUser = ({ name, email, role = 'member' }) =>
`${name} <${email}> (${role})`;
// Default parameters over conditionals
const paginate = (items, page = 1, perPage = 10) =>
items.slice((page - 1) * perPage, page * perPage);
class Query {
constructor(data) {
this._data = data;
this._filters = [];
this._sort = null;
this._limit = null;
}
where(predicate) {
this._filters.push(predicate);
return this; // Always return this for chaining
}
sortBy(key, direction = 'asc') {
this._sort = { key, direction };
return this;
}
limit(n) {
this._limit = n;
return this;
}
value() {
let result = this._data;
for (const filter of this._filters) {
result = result.filter(filter);
}
if (this._sort) {
const { key, direction } = .;
mult = direction === ? : -;
result = [...result].( a[key] > b[key] ? mult : -mult);
}
(.) {
result = result.(, .);
}
result;
}
}
topUsers = (users)
.( u.)
.( u. > )
.(, )
.()
.();
// Good: defaults that work, options that customize
const fetch = (url, options = {}) => {
const config = {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
timeout: 5000,
retries: 3,
...options
};
// ...
};
// Most calls are simple
fetch('/api/users');
// Complex when needed
fetch('/api/users', { method: 'POST', body: data });
// Predicates start with is/has/can
const isEmpty = (arr) => arr.length === 0;
const hasChildren = (node) => node.children?.length > 0;
const canEdit = (user, doc) => doc.ownerId === user.id;
// Transformers are verbs or "to" + noun
const slugify = (str) => str.toLowerCase().replace(/\s+/g, '-');
const toArray = (value) => Array.isArray(value) ? value : [value];
// Getters match property names
const getName = (obj) => obj.name;
const getById = (id) => (arr) => arr.find(x => x.id === id);
// Pipe: left-to-right composition
const pipe = (...fns) => (x) => fns.reduce((v, f) => f(v), x);
// Usage
const processUser = pipe(
validateEmail,
normalizePhone,
hashPassword,
saveToDatabase
);
// Compose: right-to-left (mathematical order)
const compose = (...fns) => (x) => fns.reduceRight((v, f) => f(v), x);
const memoize = (fn) => {
const cache = new Map();
return (...args) => {
const key = JSON.stringify(args);
if (!cache.has(key)) {
cache.set(key, fn(...args));
}
return cache.get(key);
};
};
const debounce = (fn, wait) => {
let timeout;
return (...args) => {
clearTimeout(timeout);
timeout = setTimeout(() => fn(...args), wait);
};
};
const throttle = (fn, wait) => {
let lastCall = 0;
return (...args) => {
const now = Date.now();
if (now - lastCall >= wait) {
lastCall = now;
fn(...args);
}
};
};
const partial = (fn, ...presetArgs) =>
(...laterArgs) => fn(...presetArgs, ...laterArgs);
// Usage
const greet = (greeting, name) => `${greeting}, ${name}!`;
const sayHello = partial(greet, 'Hello');
sayHello('World'); // "Hello, World!"
When reviewing JavaScript utilities and libraries:
thismap/filter/reduce over imperative loopsfind/some/every when appropriatethis or arguments needed?.) and nullish coalescing (??)// Bad: AbstractFactoryProviderManager
class UserServiceFactoryProvider {
createUserServiceFactory() {
return new UserServiceFactory();
}
}
// Good: just a function
const createUser = (data) => ({ id: uuid(), ...data, createdAt: Date.now() });
// Bad: abstracting on first use
const makeAdder = (x) => (y) => x + y;
const add5 = makeAdder(5);
add5(3); // Just use 5 + 3
// Good: abstract when you see the pattern repeated
// (wait until you need it in 3+ places)
// Bad: over-configured
fetch({ url: '/users', method: 'GET', format: 'json' });
// Good: simple API, options when needed
fetch('/users');
fetch('/users', { method: 'POST' });
Use for:
Skip for: