@private、@protected、@public 和 @readonly 的区别是什么?

在 JSDoc 中,@private@protected@public@readonly 分属两个完全不同的控制维度,且标准性与工具支持差异显著。以下是精准对比:


✅ 核心区别总览表

标签 控制维度 标准性 作用 TS 关键字 是否互斥 典型场景
@private 访问权限 ✅ JSDoc 官方 仅当前类内部可访问 private ✅ 三者互斥 内部实现细节、辅助方法
@protected 访问权限 ✅ JSDoc 官方 当前类 + 子类可访问 protected ✅ 三者互斥 供子类扩展的钩子、共享状态
@public 访问权限 ✅ JSDoc 官方 所有作用域可访问 public(默认) ✅ 三者互斥 显式覆盖继承的访问级别(罕见)
@readonly 可变性 非 JSDoc 标准✅ TypeDoc/TS 扩展 初始化后不可重新赋值 readonly ❌ 可与前三者任意组合 配置项、ID、常量引用

🔑 关键认知

  • @private/@protected/@public“谁能看”(访问控制)
  • @readonly“能不能改”(状态控制)
  • @public 通常冗余(未标注即默认公开)

🔍 深度解析与避坑指南

1️⃣ 访问权限三标签(互斥,三选一)

class Engine {
  /** 
   * 内部缓存(仅本类可见)
   * @private
   */
  _cache = {};

  /**
   * 子类可重写的初始化逻辑
   * @protected
   */
  _init() { }

  /**
   * 公开 API(无需 @public!)
   * (默认即为 public)
   */
  start() { }
}
  • @public 使用场景极少
    仅当父类成员被标记为 @protected,子类需显式提升为公开时使用(部分工具支持):
    class Base { /** @protected */ config = {}; }
    class PublicAPI extends Base {
      /** @public */ // 覆盖为公开(依赖工具支持)
      config;
    }
    
  • ⚠️ 默认即公开:未加任何访问标签 = @public无需显式标注(写 @public 属冗余)

2️⃣ @readonly(独立维度,可叠加)

class User {
  /** 
   * 用户ID(子类可读,全局不可改)
   * @protected
   * @readonly
   */
  protected readonly id: string;

  /** 
   * 公开版本号(所有人可读,不可改)
   * @readonly
   */
  readonly version = '1.0';
}
  • 可与任意访问标签组合@private @readonly / @protected @readonly
  • 不控制访问范围@readonly 成员若为 public,外部仍可读取(仅禁止修改)
  • 非深度只读:仅阻止重新赋值,不阻止修改对象内部属性(需配合 Object.freeze 或 TS Readonly<T>

🚫 常见误区澄清

误区 正确理解
@readonly 是访问权限标签” ❌ 它只控制可变性,与“谁能看到”无关
“必须写 @public 表示公开” 冗余!未标注即默认公开(JSDoc 规范)
@readonly 能深度冻结对象” ❌ 仅防重新赋值,obj.prop = x 仍可修改(若 prop 非 readonly)
“标准 JSDoc 工具支持 @readonly" jsdoc CLI 会忽略它;仅 VS Code/TypeDoc/TS 识别
@public 可覆盖父类 @private" ❌ 访问级别不能提升(子类无法将父类 private 变为 public)

🛠 工具行为对比

工具 @private @protected @public @readonly
TypeScript 编译器 private 强制 protected 强制 默认行为 readonly 强制
VS Code 智能提示 外部访问标黄 子类外访问标黄 无特殊标记 赋值操作标红
TypeDoc / VitePress 默认不生成文档 生成并标注 "Protected" 生成(无需标签) 标注 "Readonly"
标准 JSDoc (CLI) 隐藏 标注 无影响 完全忽略

💡 TypeDoc 默认隐藏 @private 成员(需 --excludePrivate false 显式显示)


✅ 最佳实践指南

项目类型 推荐做法
TypeScript 直接用关键字private readonly id❌ 无需 JSDoc 访问/readonly 标签
纯 JavaScript (.js) ✅ 仅当工具需要时添加:/** @protected @readonly */⚠️ 确认文档工具支持(如 TypeDoc)
文档注释 ✅ 专注写清晰描述/** 用户唯一ID(子类可读,初始化后不可变) */❌ 避免堆砌冗余标签(如 @public

🌟 终极口诀

🔒 @private“此物藏于密室,仅我可见”
👨‍👦 @protected“此物存于家祠,子女可瞻仰”
🌍 @public“此物陈列厅堂”(默认如此,无需挂牌)
🚫 @readonly“覆以琉璃罩——可观而不可触”(可置于密室/家祠/厅堂任一处)

💡 记住

  • 访问权限三选一(private/protected/public)
  • @readonly 是独立开关,可叠加在任一访问级别上
  • 现代 TS 项目:忘掉这些 JSDoc 标签,用语言关键字!
posted @ 2026-01-29 22:44  龙陌  阅读(5)  评论(0)    收藏  举报