当前位置: 首页 > news >正文

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

@private@protected@readonly 是 JSDoc 中三个常被混淆的标签,但它们分别控制不同的维度访问权限(visibility) vs 可变性(mutability)

下面从语义、用途、使用场景和工具支持等角度,清晰对比三者:


✅ 一句话总结

标签 控制什么? 谁能访问? 能否修改? 对应 TS 关键字
@private 私有访问权限 仅当前类内部 取决于是否 readonly private
@protected 受保护访问权限 当前类 + 子类 取决于是否 readonly protected
@readonly 只读不可变性 任何人(若公开) ❌ 不能修改 readonly

🔑 关键区别

  • @private / @protected“谁能看/用”(访问控制)
  • @readonly“能不能改”(状态控制)

一、详细解析

1. @private —— “仅本类可见”

  • 语义:该成员是内部实现细节外部和子类都不应访问
  • 典型场景:内部缓存、辅助方法、私有状态。
  • 示例(JavaScript)
    class Cache {/*** 内部存储对象(完全私有)* @private*/_store = {};/*** 私有清理方法* @private*/_cleanup() { /* ... */ }
    }
    
  • TypeScript 更佳写法(无需 JSDoc):
    class Cache {private _store = {};private _cleanup() { /* ... */ }
    }
    

🚫 外部或子类访问 @private 成员会被文档工具标记为“不推荐”,TS 编译器会直接报错。


2. @protected —— “本类及子类可见”

  • 语义:该成员不是公开 API,但允许子类继承和使用
  • 典型场景:供子类重写的钩子方法、共享的内部状态。
  • 示例
    class Animal {/*** 子类可访问的能量值* @protected*/protected energy = 100;/*** 子类可重写的进食逻辑* @protected*/protected eat() { this.energy += 10; }
    }class Dog extends Animal {bark() {this.eat(); // ✅ 允许:子类可访问 protected}
    }new Dog().eat(); // ❌ 不推荐!外部不应调用
    

3. @readonly —— “初始化后不可变”

  • 语义:该成员一旦赋值,就不能再被修改(强调不可变性)。
  • 与访问权限无关:它可以是 publicprotectedprivatereadonly
  • 典型场景:配置项、ID、常量引用。
  • 示例
    class User {/*** 用户唯一 ID(公开但不可变)* @readonly*/readonly id: string;constructor(id: string) {this.id = id; // 只能在构造函数中赋值}
    }const user = new User('123');
    console.log(user.id); // ✅ 可读
    user.id = '456';      // ❌ TS 报错:readonly 不能修改
    

二、组合使用(合法且常见)

这三个标签可以任意组合(只要语义合理):

组合 含义 示例
@protected + @readonly 子类可读,但任何地方都不能改 protected readonly config;
@private + @readonly 仅本类可读,且不能改 private readonly secretKey;
@public(默认) + @readonly 所有人都可读,但不能改 readonly version = '1.0';

💡 注意:@private@protected 互斥,不能同时用。


三、对比表格(核心区别)

特性 @private @protected @readonly
控制目标 访问权限 访问权限 可变性
外部能否访问 ❌ 否 ❌ 否(设计上) ✅ 能(如果是 public)
子类能否访问 ❌ 否 ✅ 能 ✅ 能(如果 accessible)
能否重新赋值 取决于是否 readonly 取决于是否 readonly ❌ 不能
TS 关键字 private protected readonly
JSDoc 必要性 JS 中需要,TS 中不需要 JS 中需要,TS 中不需要 JS 中可选,TS 中用关键字更好

四、工具行为对比

工具 @private @protected @readonly
TypeScript 编译器 private 关键字强制限制 protected 强制限制 readonly 阻止赋值
VS Code 智能提示 外部访问标黄/报错 子类外访问标黄 赋值时报错
TypeDoc / VitePress 文档中标记为 "Private"(默认隐藏) 标记为 "Protected" 标记为 "Readonly"
ESLint 可配置规则禁止访问私有成员 同上 可检测非法赋值

📌 默认情况下,TypeDoc 不会在生成的文档中显示 @private 成员(需加 --excludePrivate false 才显示)。


✅ 最佳实践建议

  1. 在 TypeScript 项目中,优先使用语言关键字

    private x = 1;
    protected y = 2;
    readonly z = 3;
    

    无需写 JSDoc 标签,除非需要额外描述。

  2. 在纯 JavaScript(.js)项目中,才需要用 JSDoc 表达意图

    /*** @private* @readonly*/
    const SECRET = 'xxx';
    
  3. 不要混淆概念

    • 想隐藏实现?→ 用 private / protected
    • 想防止误改?→ 用 readonly

🧠 记忆口诀

  • @private“我家的事,外人别管,孩子也不许插手”
  • @protected“家事可让子女参与,但外人止步”
  • @readonly“东西可以看,但请勿动手”
http://www.jsqmd.com/news/318953/

相关文章:

  • 23. 抗锯齿
  • 理解Spark RDD
  • Java毕设项目推荐-基于微信小程序的狼人杀桌游预约拼团小程序设计与实现基于springboot的剧本杀游玩一体化平台小程序的设计与实现【附源码+文档,调试定制服务】
  • Flutter for OpenHarmony 视力保护提醒App实战 - 错误处理与异常管理
  • samlib.dll文件丢失找不到问题 免费下载方法分享
  • 2026 年后端开发者路线图
  • sudo命令和su 的区别
  • 高并发服务器组件单元测试集成测试架构测试
  • 计算机Java毕设实战-基于springboot的剧本杀游玩一体化平台小程序的设计与实现剧本杀狼人杀桌游预约小程序【完整源码+LW+部署说明+演示视频,全bao一条龙等】
  • 从迎宾展示到数据闭环:校园智能接待机器人的技术演进与应用现状
  • 22. 纹理采样
  • MATLAB基于Shapley组合模型物流需求预测
  • 【课程设计/毕业设计】基于Springboot+Uniapp的剧本杀游玩一体化平台微信小程序基于springboot的剧本杀游玩一体化平台小程序的设计与实现【附源码、数据库、万字文档】
  • 2026 01 29 难道是隐藏的彩蛋
  • Java毕设项目:基于springboot的剧本杀游玩一体化平台小程序的设计与实现(源码+文档,讲解、调试运行,定制等)
  • 把握AI原生应用领域可解释性的发展趋势
  • 基于Springboot在线捐赠系统【附源码+文档】
  • Java计算机毕设之基于springboot的剧本杀游玩一体化平台小程序基于Springboot+Uniapp的剧本杀游玩一体化平台微信小程序(完整前后端代码+说明文档+LW,调试定制等)
  • Redis 集合(Set)
  • 巴菲特的逆向投资心理学:在市场恐慌中保持理性
  • 《叙事生成系统剧情连贯与选择价值落地手册》
  • 【毕业设计】基于springboot的剧本杀游玩一体化平台小程序的设计与实现(源码+文档+远程调试,全bao定制等)
  • autofit.js:大屏适配工具
  • 《游戏生态模拟系统可持续自调节核心指南》
  • YOLO26涨点改进 | 全网首发、主干改进篇 | AAAI 2026 | StripNet 主干让 YOLO26 更加强大!利用 StripNet的条形卷积,提升遥感目标检测有效涨点、高效发论文
  • 插件发布到npm
  • python个人日程待办事件事务提醒系统小程序
  • 安装moltbot(未成功)
  • ARM汇编器与GNU汇编器:详细介绍与核心区别
  • python共享充电桩微信小程序_qe