javascript

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

JavaScript

JavaScript

Specification

规范说明

The words
MUST
,
MUST NOT
,
REQUIRED
,
SHALL
,
SHALL NOT
,
SHOULD
,
SHOULD NOT
,
RECOMMENDED
,
MAY
, and
OPTIONAL
are interpreted as described in RFC 2119.
Clarity is the highest JavaScript virtue. If your code requires a comment to explain its control flow, rewrite it.
JavaScript rewards explicit, readable code. You SHOULD prefer boring patterns that are easy to understand over clever tricks that save characters.
本文中的
MUST
MUST NOT
REQUIRED
SHALL
SHALL NOT
SHOULD
SHOULD NOT
RECOMMENDED
MAY
OPTIONAL
均按照RFC 2119中的定义解释。
清晰是JavaScript的最高准则。如果你的代码需要注释来解释控制流,请重写代码。
JavaScript推崇明确、可读的代码。你应当优先选择易于理解的常规写法,而非节省字符的巧妙技巧。

References

参考文档

  • Functions, closures, composition
    references/functions.md
    — Arrow function examples, closure patterns, early return, parameter destructuring
  • Async patterns, error handling, concurrency
    references/async.md
    — Promise.all/race/any examples, cancellation, custom error classes, for-await
  • Objects, arrays, iteration, Map/Set
    references/objects-and-arrays.md
    — Iteration decision table, destructuring patterns, immutable updates, generators
  • ES modules, imports, barrel files
    references/modules.md
    — Import ordering, barrel file rationale, directory import pitfalls, dynamic imports
  • JSDoc typing, full tag catalog
    references/jsdoc.md
    — Full tag reference (@callback, @template, @enum), type assertions, class modifiers
  • General JS idioms and edge cases
    references/idioms.md
    — Variable/naming examples, equality coercion table, modern syntax patterns
  • 函数、闭包、组合
    references/functions.md
    — 箭头函数示例、闭包模式、提前返回、参数解构
  • 异步模式、错误处理、并发
    references/async.md
    — Promise.all/race/any示例、取消操作、自定义错误类、for-await
  • 对象、数组、迭代、Map/Set
    references/objects-and-arrays.md
    — 迭代决策表、解构模式、不可变更新、生成器
  • ES模块、导入、桶文件
    references/modules.md
    — 导入排序、桶文件原理、目录导入陷阱、动态导入
  • JSDoc类型、完整标签目录
    references/jsdoc.md
    — 完整标签参考(@callback、@template、@enum)、类型断言、类修饰符
  • 通用JS惯用写法与边界情况
    references/idioms.md
    — 变量/命名示例、相等强制转换表、现代语法模式

Requests

工具要求

  • You are RECOMMENDED to use
    bun
    as the package manager unless told otherwise.
  • 除非另有说明,推荐使用
    bun
    作为包管理器。

Variables and Declarations

变量与声明

  • const
    by default.
    You SHOULD use
    let
    only when reassignment is required. You MUST NOT use
    var
    .
  • const
    prevents reassignment, not mutation.
    Objects and arrays declared with
    const
    can still be mutated.
  • Block scope only.
    let
    /
    const
    are block-scoped;
    var
    is function-scoped and hoists — this causes bugs in loops and conditionals.
  • One declaration per line. You MUST NOT chain
    const a = 1, b = 2
    .
  • Group declarations.
    const
    first, then
    let
    .
  • 默认使用
    const
    。仅当需要重新赋值时才应使用
    let
    。严禁使用
    var
  • const
    阻止重赋值,但不阻止突变
    。用
    const
    声明的对象和数组仍然可以被修改。
  • 仅使用块级作用域
    let
    /
    const
    是块级作用域;
    var
    是函数级作用域且存在变量提升——这会在循环和条件语句中引发bug。
  • 每行一个声明。严禁链式声明
    const a = 1, b = 2
  • 分组声明。先声明
    const
    ,再声明
    let

Naming

命名规范

EntityStyleExamples
Variables, functionscamelCase
userName
,
fetchData
Classes, constructorsPascalCase
UserService
,
HttpClient
True compile-time constantsSCREAMING_SNAKE_CASE
MAX_RETRIES
,
API_BASE_URL
Private fields/methods
#
prefix (class)
#count
,
#validate()
Booleans
is
/
has
/
can
/
should
prefix
isValid
,
hasAccess
File nameskebab-case or camelCase
user-service.js
,
userService.js
  • SCREAMING_SNAKE_CASE is for true constants only — values known at compile time, never computed at runtime. A variable holding a function return value uses camelCase.
  • Descriptive names.
    userCount
    not
    n
    . Short names (
    i
    ,
    x
    ) only in tiny scopes (loop indices, simple arrow callbacks).
  • Accepted abbreviations:
    url
    ,
    id
    ,
    err
    ,
    ctx
    ,
    req
    ,
    res
    — universally understood. Avoid all others.
  • No redundant context.
    car.make
    not
    car.carMake
    .
  • Consistent vocabulary. Use the same word for the same concept throughout a codebase —
    getUser()
    everywhere, not
    getUserInfo()
    /
    getClientData()
    /
    getCustomerRecord()
    .
实体类型命名风格示例
变量、函数camelCase(小驼峰)
userName
,
fetchData
类、构造函数PascalCase(大驼峰)
UserService
,
HttpClient
真正的编译时常量SCREAMING_SNAKE_CASE(全大写下划线)
MAX_RETRIES
,
API_BASE_URL
私有字段/方法
#
前缀(类中)
#count
,
#validate()
布尔值
is
/
has
/
can
/
should
前缀
isValid
,
hasAccess
文件名kebab-case(短横线)或camelCase
user-service.js
,
userService.js
  • SCREAMING_SNAKE_CASE仅用于真正的常量——编译时已知的值,运行时绝不计算。存储函数返回值的变量使用camelCase。
  • 使用描述性名称。用
    userCount
    而非
    n
    。仅在极小作用域(循环索引、简单箭头回调)中使用短名称(
    i
    x
    )。
  • 可接受的缩写
    url
    id
    err
    ctx
    req
    res
    ——这些是通用理解的缩写。避免其他所有缩写。
  • 无冗余上下文。用
    car.make
    而非
    car.carMake
  • 词汇保持一致。在整个代码库中对同一概念使用相同词汇——全程使用
    getUser()
    ,而非
    getUserInfo()
    /
    getClientData()
    /
    getCustomerRecord()

Equality and Safety

相等性与安全性

  • Equality MUST use
    ===
    and
    !==
    .
    You MUST NOT use
    ==
    except for
    value == null
    (checks both
    null
    and
    undefined
    ).
  • ??
    over
    ||
    for defaults —
    ||
    treats
    0
    ,
    ""
    ,
    false
    as falsy.
  • ?.
    for optional access.
    Don't overuse — missing data you expect SHOULD throw, not silently return
    undefined
    .
  • Know the falsy values:
    false
    ,
    0
    ,
    -0
    ,
    0n
    ,
    ""
    ,
    null
    ,
    undefined
    ,
    NaN
    . Everything else is truthy, including
    []
    ,
    {}
    , and
    "0"
    .
  • 相等性必须使用
    ===
    !==
    。严禁使用
    ==
    ,除非是
    value == null
    (同时检查
    null
    undefined
    )。
  • 默认值使用
    ??
    而非
    ||
    ——
    ||
    会将
    0
    ""
    false
    视为假值。
  • 可选访问使用
    ?.
    。不要过度使用——预期存在的数据缺失时应当抛出错误,而非静默返回
    undefined
  • 了解假值
    false
    0
    -0
    0n
    ""
    null
    undefined
    NaN
    。其他所有值均为真值,包括
    []
    {}
    "0"

Ternary Operator

三元运算符

  • One-liners or split-per-branch only. Ternaries are acceptable in two forms:
    js
    // OK — fits on one line
    const label = isActive ? 'Active' : 'Inactive'
    
    // OK — each branch on its own line
    const label = isActive ? buildActiveLabel(user) : buildInactiveLabel(user)
    Any ternary that doesn't fit one of these two patterns MUST be rewritten as
    if
    /
    else
    or early return.
  • Nested ternaries MUST NOT be used. Use
    if
    /
    else
    , early returns, or a lookup object.
  • 仅允许单行或按分支拆分的写法。三元表达式仅接受以下两种形式:
    js
    // 允许——单行展示
    const label = isActive ? 'Active' : 'Inactive'
    
    // 允许——每个分支单独一行
    const label = isActive ? buildActiveLabel(user) : buildInactiveLabel(user)
    任何不符合这两种模式的三元表达式必须重写为
    if
    /
    else
    或提前返回。
  • 严禁使用嵌套三元表达式。使用
    if
    /
    else
    、提前返回或查找对象替代。

Modern Syntax

现代语法

  • Template literals for string interpolation:
    `Hello, ${name}`
    . Don't use template literals for strings without interpolation — use plain quotes.
  • Spread for copies:
    { ...obj }
    and
    [...arr]
    . You SHOULD NOT use
    Object.assign
    .
  • Rest parameters to collect remaining:
    const { id, ...rest } = user
    .
  • Shorthand properties:
    { name, age }
    not
    { name: name, age: age }
    . Group shorthand properties at the top of object literals.
  • Computed property names:
    { [key]: value, [
    ${key}Date
    ]: new Date() }
    .
  • Logical assignment operators:
    opts.timeout ??= 5000
    (assign if nullish),
    opts.name ||= "default"
    (assign if falsy),
    opts.handler &&= wrap(opts.handler)
    (assign if truthy).
  • 字符串插值使用模板字面量
    `Hello, ${name}`
    。不要对无插值的字符串使用模板字面量——使用普通引号。
  • 复制使用扩展运算符
    { ...obj }
    [...arr]
    。不应使用
    Object.assign
  • 剩余参数收集剩余值
    const { id, ...rest } = user
  • 属性简写
    { name, age }
    而非
    { name: name, age: age }
    。将简写属性放在对象字面量的顶部。
  • 计算属性名
    { [key]: value, [
    ${key}Date
    ]: new Date() }
  • 逻辑赋值运算符
    opts.timeout ??= 5000
    (当值为nullish时赋值)、
    opts.name ||= "default"
    (当值为假值时赋值)、
    opts.handler &&= wrap(opts.handler)
    (当值为真值时赋值)。

Functions

函数

  • Arrow functions for callbacks and anonymous functions. Use function declarations only when hoisting or
    this
    binding is needed.
  • Prefer parentheses around arrow function parameters even for single params — smaller diffs when adding/removing parameters.
  • Implicit return for single expressions (no braces). Explicit return (braces) for multi-statement bodies.
  • Arrow functions capture lexical
    this
    — they do NOT have their own
    this
    . You MUST NOT use arrow functions as object methods or on prototypes.
  • Destructured options for 3+ parameters. Self-documenting and order-independent.
  • Default parameters over
    ||
    or manual checks. Defaults are evaluated left-to-right and can reference earlier params.
  • Rest parameters over
    arguments
    object.
    arguments
    is array-like, not a real Array.
  • Early return. Guard clauses first, happy path flat. Reduce nesting.
  • One function, one job. If the name contains "and", split it.
  • Keep functions under ~30 lines. Extract helpers. Use composition over complex branching.
  • Prefer pure functions (same input = same output, no side effects). Isolate side effects (DOM, network, logging) — don't hide them inside data transformations.
  • Closures retain references to outer variables, not copies. Be cautious with large objects captured unintentionally — they won't be garbage collected until the closure is released.
  • 回调和匿名函数使用箭头函数。仅当需要变量提升或
    this
    绑定时才使用函数声明。
  • 箭头函数参数优先加括号——即使是单个参数,这样在添加/移除参数时差异更小。
  • 单表达式使用隐式返回(无大括号)。多语句体使用显式返回(带大括号)。
  • 箭头函数捕获词法作用域的
    this
    ——它们没有自己的
    this
    。严禁将箭头函数用作对象方法或原型方法。
  • 参数数量≥3时使用解构选项。自文档化且参数顺序无关。
  • 默认参数优于
    ||
    或手动检查
    。默认值从左到右求值,可引用之前的参数。
  • 剩余参数优于
    arguments
    对象
    arguments
    是类数组,而非真正的数组。
  • 提前返回。先写守卫子句,让主逻辑保持扁平化。减少嵌套。
  • 单一职责。如果函数名包含"and",则拆分它。
  • 函数长度控制在~30行以内。提取辅助函数。优先使用组合而非复杂分支。
  • 优先使用纯函数(相同输入=相同输出,无副作用)。隔离副作用(DOM操作、网络请求、日志)——不要隐藏在数据转换中。
  • 闭包保留对外部变量的引用,而非副本。谨慎处理意外捕获的大型对象——在闭包释放前它们不会被垃圾回收。

Async

异步处理

  • async
    /
    await
    over
    .then()
    chains
    for sequential operations.
  • Promises MUST be awaited or explicitly handled. Missing
    await
    = floating promise = silent failures.
  • return await
    only inside
    try
    blocks
    where you need to catch the awaited error. Otherwise just
    return promise
    — no need for
    async
    wrapper.
  • Promise.all
    for independent parallel work. Rejects on first rejection.
  • Promise.allSettled
    when all results matter regardless of individual failures.
  • Promise.race
    for timeouts.
    Promise.any
    for fallbacks (rejects only when ALL reject).
  • Avoid sequential awaits in loops. Use
    Promise.all(items.map(...))
    for parallel. Use a concurrency limiter (e.g.
    p-map
    ) for large arrays.
  • You MUST throw
    Error
    objects
    , not strings or plain objects — strings lose stack traces.
  • Use
    Error.isError(error)
    when checking whether a caught value is an
    Error
    . Do not use
    error instanceof Error
    .
  • Custom error classes when callers need to distinguish errors: extend
    Error
    , set
    this.name
    , add context properties.
  • You MUST NOT swallow errors. Every
    catch
    MUST handle, rethrow, or report. Empty
    catch
    blocks hide bugs.
    console.log(err)
    alone is not handling.
  • Let errors propagate to a top-level handler when possible. Don't wrap every
    await
    in
    try
    /
    catch
    — only where you need to handle at that level.
  • Attach
    .catch()
    to non-awaited promise chains.
    Unhandled rejections crash Node.js. Fire-and-forget:
    fetchData().catch(reportError)
    .
  • You SHOULD use
    new Promise()
    only to wrap callback-based APIs.
    Most async code SHOULD compose existing promises with
    async
    /
    await
    .
  • AbortController
    for cancellable async operations: pass
    { signal }
    to
    fetch
    and other APIs.
  • for await...of
    for async iterables (streams, async generators).
  • 顺序操作优先使用
    async
    /
    await
    而非
    .then()
  • Promise必须被await或显式处理。遗漏
    await
    会导致浮动Promise,进而引发静默失败。
  • 仅在
    try
    块内使用
    return await
    ——此时需要捕获await的错误。否则直接
    return promise
    即可,无需
    async
    包装。
  • **
    Promise.all
    **用于独立的并行任务。第一个Promise拒绝时整体拒绝。
  • **
    Promise.allSettled
    **用于无论单个任务是否失败,都需要所有结果的场景。
  • **
    Promise.race
    用于超时场景。
    Promise.any
    **用于降级场景(仅当所有Promise都拒绝时才拒绝)。
  • 避免在循环中顺序await。使用
    Promise.all(items.map(...))
    实现并行。处理大型数组时使用并发限制器(如
    p-map
    )。
  • 必须抛出
    Error
    对象
    ,而非字符串或普通对象——字符串会丢失堆栈跟踪。
  • 检查捕获值是否为Error时使用
    Error.isError(error)
    。不要使用
    error instanceof Error
  • 当调用者需要区分错误时使用自定义错误类——继承
    Error
    ,设置
    this.name
    ,添加上下文属性。
  • 严禁吞掉错误。每个
    catch
    必须处理、重新抛出或上报。空
    catch
    块会隐藏bug。仅
    console.log(err)
    不视为处理错误。
  • 尽可能让错误传播到顶层处理器。不要给每个
    await
    都包裹
    try
    /
    catch
    ——仅在需要在当前层级处理时使用。
  • 非await的Promise链必须附加
    .catch()
    。未处理的拒绝会导致Node.js崩溃。即发即弃场景:
    fetchData().catch(reportError)
  • 仅在包装基于回调的API时使用
    new Promise()
    。大多数异步代码应当通过
    async
    /
    await
    组合现有Promise。
  • **
    AbortController
    **用于可取消的异步操作:将
    { signal }
    传递给
    fetch
    和其他API。
  • **
    for await...of
    **用于异步可迭代对象(流、异步生成器)。

Modules

模块

  • ES modules are REQUIRED for new code.
    import
    /
    export
    for all new code. CommonJS (
    require
    ) is legacy — use only when runtime requires it.
  • Named exports over default exports. Default exports cause inconsistent naming across importers. Exception: default exports acceptable when REQUIRED by framework convention (Next.js pages, Remix routes).
  • Don't export mutable
    let
    bindings.
    Export accessor functions instead:
    export function getCount()
    not
    export let count
    .
  • Imports at the top, grouped with blank lines: built-in (
    node:fs
    ), external (
    express
    ), internal (
    ./utils
    ).
  • Import paths MUST include file extensions
    "./user.js"
    , not
    "./user"
    . Extensionless imports vary across runtimes.
  • No directory imports. Import from the file directly, not from a folder that resolves to
    index.js
    .
  • No barrel files in subdirectories.
    index.js
    re-exports create indirection and hurt tree-shaking. Acceptable only as a standalone package entry point where the runtime can enforce the boundary via
    package.json
    exports
    .
  • No circular dependencies. Extract shared code to a third module, merge tightly coupled modules, or use dependency injection.
  • No wildcard re-exports. Explicit re-exports only — wildcards bypass tree-shaking.
  • Merge imports from the same module into a single statement.
  • Namespace imports (
    import * as dateFns
    ) for large modules (5+ items). Prefer named imports when importing fewer than ~5 items.
  • Dynamic imports (
    import()
    ) for code splitting and lazy loading: routes loaded on navigation, large conditional dependencies, feature flags.
  • One concern per module. If a module exports unrelated functionality, split it.
  • Side-effect imports (
    import "./polyfill.js"
    ) SHOULD be rare. Document why.
  • 新代码必须使用ES模块。所有新代码使用
    import
    /
    export
    。CommonJS(
    require
    )属于遗留语法——仅当运行环境要求时才使用。
  • 命名导出优于默认导出。默认导出会导致导入者命名不一致。例外:当框架约定要求时可使用默认导出(Next.js页面、Remix路由)。
  • 不要导出可变的
    let
    绑定
    。改为导出访问器函数:
    export function getCount()
    而非
    export let count
  • 导入语句放在顶部,按空行分组:内置模块(
    node:fs
    )、外部模块(
    express
    )、内部模块(
    ./utils
    )。
  • 导入路径必须包含文件扩展名——
    "./user.js"
    ,而非
    "./user"
    。无扩展名导入在不同运行环境中表现不同。
  • 不要使用目录导入。直接从文件导入,而非从解析到
    index.js
    的文件夹导入。
  • 子目录中不要使用桶文件
    index.js
    重导出会增加间接性并影响摇树优化。仅在独立包的入口点允许使用,此时运行时可通过
    package.json
    exports
    字段 enforce 边界。
  • 不要存在循环依赖。将共享代码提取到第三个模块,合并紧密耦合的模块,或使用依赖注入。
  • 不要使用通配符重导出。仅使用显式重导出——通配符会绕过摇树优化。
  • 将同一模块的导入合并为单个语句
  • 大型模块(≥5个导入项)使用命名空间导入
    import * as dateFns
    )。导入项少于~5个时优先使用命名导入。
  • 动态导入
    import()
    )用于代码分割和懒加载:导航时加载路由、大型条件依赖、功能开关。
  • 每个模块单一职责。如果一个模块导出不相关的功能,拆分它。
  • 副作用导入
    import "./polyfill.js"
    )应当尽量少用。并说明原因。

Objects and Arrays

对象与数组

  • Literal syntax.
    {}
    and
    []
    , never
    new Object()
    /
    new Array()
    .
  • Use method shorthand on objects:
    greet() { }
    not
    greet: function() { }
    .
  • Spread for copies.
    { ...obj }
    and
    [...arr]
    . Prefer over
    Object.assign
    .
  • Destructure to extract properties. Prefer parameter destructuring.
  • Dot notation for static properties, brackets for dynamic:
    user.name
    vs
    user[dynamicKey]
    .
  • Object.hasOwn(obj, key)
    instead of
    obj.hasOwnProperty(key)
    .
  • Functional array methods (
    map
    ,
    filter
    ,
    find
    ,
    some
    ,
    every
    ,
    flatMap
    ,
    reduce
    ) over imperative loops for data transformation.
  • Always return in
    map
    ,
    filter
    ,
    reduce
    callbacks.
  • Array.from(arrayLike)
    for array-like objects (not spread).
    Array.from(iterable, mapFn)
    instead of
    [...iterable].map(mapFn)
    — avoids intermediate array.
  • Don't mutate inputs. Return new objects/arrays. Immutable update patterns: add
    [...arr, item]
    , remove
    arr.filter(...)
    , update
    arr.map(...)
    .
  • for...of
    for side-effect loops. Never
    for...in
    on arrays.
  • Return objects for multiple values, not arrays — callers don't depend on order.
  • Built-in prototypes MUST NOT be extended (
    Array.prototype
    ,
    Object.prototype
    ). Use utility functions or subclasses.
Prefer
for...of
for side-effect loops,
Array.prototype
methods (
.map
,
.filter
,
.reduce
,
.find
,
.some
,
.every
) for data transforms,
for
for index-needed loops. See
references/objects-and-arrays.md
for the full iteration decision table.
Use
Map
when keys aren't strings or are user-provided (avoids prototype pollution). Use
Set
for dedup (
[...new Set(items)]
). Use generators (
function*
) for lazy sequences and deferred computation.
  • 使用字面量语法
    {}
    []
    ,绝不使用
    new Object()
    /
    new Array()
  • 对象上使用方法简写
    greet() { }
    而非
    greet: function() { }
  • 复制使用扩展运算符
    { ...obj }
    [...arr]
    。优先于
    Object.assign
  • 解构提取属性。优先使用参数解构。
  • 静态属性使用点表示法,动态属性使用方括号
    user.name
    vs
    user[dynamicKey]
  • 使用
    Object.hasOwn(obj, key)
    替代
    obj.hasOwnProperty(key)
  • 数据转换优先使用函数式数组方法
    map
    filter
    find
    some
    every
    flatMap
    reduce
    )而非命令式循环。
  • map
    filter
    reduce
    的回调必须始终返回值
  • 类数组对象使用
    Array.from(arrayLike)
    (而非扩展运算符)。
    Array.from(iterable, mapFn)
    替代
    [...iterable].map(mapFn)
    ——避免中间数组。
  • 不要修改输入。返回新的对象/数组。不可变更新模式:添加
    [...arr, item]
    、删除
    arr.filter(...)
    、更新
    arr.map(...)
  • 副作用循环使用
    for...of
    。绝不使用
    for...in
    遍历数组。
  • 多值返回使用对象而非数组——调用者无需依赖顺序。
  • 严禁扩展内置原型
    Array.prototype
    Object.prototype
    )。使用工具函数或子类。
副作用循环优先使用
for...of
,数据转换优先使用
Array.prototype
方法(
.map
.filter
.reduce
.find
.some
.every
),需要索引的循环使用
for
。完整的迭代决策表请参见
references/objects-and-arrays.md
当键不是字符串或由用户提供时使用
Map
(避免原型污染)。去重使用
Set
[...new Set(items)]
)。惰性序列和延迟计算使用生成器(
function*
)。

Classes

  • ES
    class
    syntax is REQUIRED.
    Do not use function constructors or prototype manipulation.
  • #private
    fields
    for encapsulation. Not
    _
    convention.
  • Composition over inheritance. Use
    extends
    only for true "is-a" relationships.
  • No empty constructors. If the constructor only calls
    super()
    , omit it.
  • Static methods for operations that don't need instance state.
  • Methods can return
    this
    for fluent/chainable APIs.
  • Don't force classes when plain functions and objects suffice. A class with one method is a function in disguise.
  • 必须使用ES
    class
    语法
    。不要使用函数构造函数或原型操作。
  • 封装使用
    #private
    字段
    。不要使用
    _
    约定。
  • 组合优于继承。仅当存在真正的"is-a"关系时使用
    extends
  • 不要使用空构造函数。如果构造函数仅调用
    super()
    ,则省略它。
  • 无需实例状态的操作使用静态方法
  • 方法可返回
    this
    以实现流畅/链式API
  • 当普通函数和对象足够时,不要强行使用类。只有一个方法的类本质上是伪装的函数。

JSDoc Typing

JSDoc类型

For pure JavaScript projects that don't use TypeScript, use JSDoc annotations to provide type safety through editor tooling. Enable
// @ts-check
at file top or
checkJs
in
jsconfig.json
.
Core tags:
@type
,
@param
,
@returns
,
@typedef
(with
@property
),
@template
. See
references/jsdoc.md
for the full tag catalog including
@callback
,
@enum
, class modifiers, and type import syntax.
对于不使用TypeScript的纯JavaScript项目,使用JSDoc注释通过编辑器工具提供类型安全。在文件顶部启用
// @ts-check
或在
jsconfig.json
中设置
checkJs
核心标签:
@type
@param
@returns
@typedef
(配合
@property
)、
@template
。完整的标签目录包括
@callback
@enum
、类修饰符和类型导入语法,请参见
references/jsdoc.md

JSDoc Best Practices

JSDoc最佳实践

  • Annotate public API boundaries — exported functions, classes, module-level variables. Internal code often needs fewer annotations; types flow from context.
  • Prefer inline TypeScript syntax in JSDoc types:
    {string | number}
    over
    {(string|number)}
    .
  • Use
    @typedef
    for shared shapes
    — define once near file top or in
    types.js
    .
  • Don't annotate the obvious — if
    const x = 5
    is clearly a number, skip
    @type
    .
  • 标注公共API边界——导出的函数、类、模块级变量。内部代码通常需要更少的注释;类型会从上下文自动推导。
  • JSDoc类型中优先使用内联TypeScript语法
    {string | number}
    优于
    {(string|number)}
  • 共享结构使用
    @typedef
    ——在文件顶部或
    types.js
    中定义一次。
  • 不要标注显而易见的类型——如果
    const x = 5
    明显是数字,跳过
    @type

Application

规范应用

When writing JavaScript code:
  • You MUST apply all conventions silently — don't narrate each rule being followed.
  • If an existing codebase contradicts a convention, you MUST follow the codebase and flag the divergence once.
When reviewing JavaScript code:
  • You MUST cite the specific violation and show the fix inline.
  • You MUST NOT lecture or quote the rule — state what's wrong and how to fix it.
Bad review comment:
  "According to best practices, use const instead of let
   when the variable is never reassigned."

Good review comment:
  "`let` -> `const` — `config` is never reassigned."
编写JavaScript代码时:
  • 必须静默应用所有规范——无需逐一说明遵循的规则。
  • 如果现有代码库与规范冲突,必须遵循代码库的写法,并一次性标注差异点。
评审JavaScript代码时:
  • 必须明确指出具体违规点,并在代码中展示修复方案。
  • 不要说教或引用规则原文——直接说明问题所在及修复方式。
不好的评审评论:
  "根据最佳实践,当变量无需重新赋值时应使用const而非let。"

好的评审评论:
  "`let` -> `const` — `config`从未被重新赋值。"

Code Navigation — LSP Required

代码导航——必须使用LSP

A
typescript-language-server
LSP server is configured for all JS/TS file types (
.js
,
.jsx
,
.ts
,
.tsx
,
.mjs
,
.cjs
,
.mts
,
.cts
). You MUST use LSP tools for code navigation instead of Grep or Glob. LSP understands module resolution, type inference, scope rules, and project boundaries — text search does not.
所有JS/TS文件类型(
.js
.jsx
.ts
.tsx
.mjs
.cjs
.mts
.cts
)均配置了
typescript-language-server
LSP服务器。必须使用LSP工具进行代码导航,而非Grep或Glob。LSP理解模块解析、类型推断、作用域规则和项目边界——文本搜索无法做到这些。

Tool Routing

工具使用指南

  • Find where a function/class/variable is defined
    goToDefinition
    — Resolves imports, re-exports, aliases
  • Find all usages of a symbol
    findReferences
    — Scope-aware, no false positives from string matches
  • Get type signature, docs, or return types
    hover
    — Instant type info without reading source files
  • List all exports/symbols in a file
    documentSymbol
    — Structured output vs grepping for
    function
    /
    class
    /
    export
  • Find a symbol by name across the project
    workspaceSymbol
    — Searches all modules
  • Find implementations of an interface
    goToImplementation
    — Knows the type system
  • Find what calls a function
    incomingCalls
    — Precise call graph across module boundaries
  • Find what a function calls
    outgoingCalls
    — Structured dependency map
Grep/Glob remain appropriate for: text in comments, string literals, log messages, TODO markers, config values, env vars, CSS classes, file name patterns, URLs, error message text.
When spawning subagents for JS/TS codebase exploration, you MUST instruct them to use LSP tools. Subagents have access to the same LSP server.
  • 查找函数/类/变量的定义位置
    goToDefinition
    — 解析导入、重导出、别名
  • 查找符号的所有引用
    findReferences
    — 作用域感知,无字符串匹配导致的误报
  • 获取类型签名、文档或返回类型
    hover
    — 无需阅读源文件即可获取即时类型信息
  • 列出文件中的所有导出/符号
    documentSymbol
    — 结构化输出,优于搜索
    function
    /
    class
    /
    export
  • 在项目中按名称查找符号
    workspaceSymbol
    — 搜索所有模块
  • 查找接口的实现
    goToImplementation
    — 了解类型系统
  • 查找调用某个函数的位置
    incomingCalls
    — 跨模块边界的精确调用图
  • 查找某个函数调用的内容
    outgoingCalls
    — 结构化依赖图
Grep/Glob仍适用于:注释中的文本、字符串字面量、日志消息、TODO标记、配置值、环境变量、CSS类、文件名模式、URL、错误消息文本。
当生成子代理探索JS/TS代码库时,必须指示它们使用LSP工具。子代理可访问同一LSP服务器。

Integration

技能集成

The coding skill governs workflow; this skill governs JavaScript implementation choices. For TypeScript projects, the typescript skill extends this one.
coding技能管控工作流;本技能管控JavaScript实现选择。对于TypeScript项目,typescript技能是本技能的扩展。",