鸿蒙中 const 和 readonly区别

本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

鸿蒙(HarmonyOS)开发中,constreadonly 都用于定义不可变的变量或属性,但它们的应用场景和行为有显著区别:

1. const:编译时常量

特点
  • 作用范围:仅用于变量声明(let 和 var 的替代)。
  • 赋值时机:必须在声明时初始化,且后续不可修改。
  • 类型推断:自动推断为字面量类型(如 const x = 10 的类型是 10,而非 number)。
  • 编译行为:在编译阶段会被直接替换为常量值(类似宏替换)。
示例
const PI = 3.14; // 声明时必须初始化
// PI = 3.14159; // 编译错误:无法重新赋值

const config = { name: "HarmonyOS" };
config.name = "OpenHarmony"; // 允许!const 仅限制引用不可变,对象属性仍可变
适用场景
  • 定义全局或局部常量(如数学常量、配置项)。
  • 需要编译时优化的简单值。

2. readonly:运行时常量

特点
  • 作用范围:主要用于类属性、接口属性或对象属性。
  • 赋值时机
    • 类属性:可在声明时或构造函数中初始化。
    • 接口/对象:必须在声明时初始化。
  • 类型行为:保留原始类型(如 readonly x: number 的类型是 number)。
  • 运行行为:在运行时检查赋值操作,禁止修改。
示例

(1)类属性

class Device {
  readonly id: string;
  constructor(id: string) {
    this.id = id; // 允许在构造函数中赋值
  }
}
const d = new Device("123");
// d.id = "456"; // 编译错误:不可修改

(2)接口/对象

interface AppConfig {
  readonly version: string;
}
const config: AppConfig = { version: "1.0" };
// config.version = "2.0"; // 编译错误:不可修改
适用场景
  • 定义对象或类的不可变属性(如组件配置、实体类ID)。
  • 需要运行时保护的复杂数据结构。

核心区别对比

特性constreadonly
作用对象变量类属性、接口属性、对象属性
可变性引用不可变(对象属性可变)属性完全不可变
初始化时机声明时必须初始化类属性可在构造函数中初始化
类型推断推断为字面量类型(如 10保留原始类型(如 number
编译/运行时编译时替换为值运行时检查

实际应用建议

  1. 基础常量 使用 const 定义简单值(如字符串、数字):
   const MAX_USERS = 100;

      2. 对象/类属性 使用 readonly 确保深层不可变性

   interface User {
     readonly id: string;
     name: string;
   }
   const user: User = { id: "001", name: "Alice" };
   // user.id = "002"; // 禁止
   user.name = "Bob"; // 允许

     3. 结合使用 对对象引用和属性同时锁定

   const DEFAULT_CONFIG: Readonly<AppConfig> = { version: "1.0" };
   // DEFAULT_CONFIG.version = "2.0"; // 禁止(Readonly 泛型将所有属性设为 readonly)

常见误区

  • 误区1:认为 const 能完全冻结对象。 纠正const 仅限制变量引用,对象属性仍可变。需配合 Object.freeze() 或 Readonly<T>
  • 误区2:在构造函数外给 readonly 属性赋值。 纠正readonly 类属性只能在声明时或构造函数中初始化。
<think>好的,用户现在问的是鸿蒙开发中变量的修饰符,比如let、const、static这些。首先,我需要回忆鸿蒙应用开发的主要语言,应该是JavaArkTS(之前叫eTS)。用户可能指的是ArkTS,因为鸿蒙现在主推ArkTS作为应用开发语言。所以需要分ArkTSJava两种情况来回答,但用户可能更关注ArkTS。首先,ArkTS是TypeScript的扩展,所以基础的TS修饰符如let、const肯定有,但鸿蒙可能有自己的扩展。然后,static在类中使用,还有可能包括访问控制修饰符如public、private、protected,以及响应式变量相关的修饰符如@State、@Link、@Prop等,这些是鸿蒙特有的状态管理修饰符。需要先整理ArkTS中的变量修饰符,包括基础的作用域修饰符(let、const)、类成员修饰符(static、public、private、protected)、响应式修饰符(@State、@Link等),以及可能的其他修饰符如readonly。然后,Java部分在鸿蒙中可能用于原生应用开发,但可能用户更关注ArkTS,所以需要重点说明ArkTS的情况,同时简要提及Java的情况,避免遗漏。需要注意用户提到的例子有let、const、static,所以需要覆盖这些,并扩展其他可能的修饰符。例如,在ArkTS中,letconst是变量声明的基本修饰符,static用于类的静态成员,访问控制修饰符,以及响应式状态修饰符。需要解释每个修饰符的作用使用场景,比如let是可变变量,const是不可变变量,static属于类而不是实例,@State用于组件状态管理等。最后,确保回答结构清晰,分点说明,可能分为基础变量修饰符、类成员修饰符、响应式状态修饰符等部分。同时,用户可能想知道这些修饰符在鸿蒙开发中的具体应用,所以需要结合鸿蒙开发场景举例。需要验证是否有遗漏的修饰符,比如ArkTS中的@Builder、@Entry等是否属于变量修饰符?可能不是,@Entry是装饰器用于标记组件入口,而变量修饰符主要是影响变量的作用域、可变性或状态管理的。总结,回答的结构应该是先介绍ArkTS中的变量修饰符,包括基础(let、const)、类成员(static、访问控制)、响应式(@State等),然后简要提Java中的情况,最后总结。</think> 在鸿蒙HarmonyOS开发中,变量修饰符的使用与开发语言密切相关。目前鸿蒙应用开发主要使用 **ArkTS(应用开发首选语言,TypeScript扩展)** **Java(部分原生场景)**,两者的变量修饰符有所不同。以下分别说明: --- ### 一、ArkTS 中的变量修饰符 ArkTS 是鸿蒙主推的应用开发语言,基于 TypeScript 扩展,支持类型系统鸿蒙特有的状态管理机制。其变量修饰符可分为 **基础作用域修饰符**、**类成员修饰符** **响应式状态修饰符** 三类。 #### 1. 基础作用域与可变性修饰符(通用) 用于控制变量的作用域(如函数/块级作用域)值的可变性: - **`let`**:声明块级作用域的可变变量(可重新赋值)。 示例: ```typescript let count = 0; count = 1; // 合法(可重新赋值) ``` - **`const`**:声明块级作用域的不可变变量(初始化后不可重新赋值,但对象属性可修改)。 示例: ```typescript const obj = { name: "Alice" }; obj.name = "Bob"; // 合法(修改对象属性) obj = { name: "Bob" }; // 报错(不可重新赋值) ``` - **`var`**:声明函数作用域的可变变量(ArkTS 中不推荐使用,优先用 `let`)。 #### 2. 类成员修饰符(用于类属性/方法) 控制类成员的访问权限、静态性等: - **`public`**(默认):公开成员,类内外均可访问。 - **`private`**:私有成员,仅类内部可访问(子类也不可访问)。 - **`protected`**:受保护成员,仅类内部或子类可访问。 - **`static`**:静态成员(属于类本身,而非实例),通过类名直接访问。 示例: ```typescript class User { public id: number; // 公开属性 private name: string; // 私有属性(仅类内部访问) static defaultAge = 18; // 静态属性(通过 User.defaultAge 访问) constructor(id: number, name: string) { this.id = id; this.name = name; } protected getInfo() { // 受保护方法(仅类/子类访问) return `ID: ${this.id}, Name: ${this.name}`; } } ``` #### 3. 响应式状态修饰符(鸿蒙特有,用于UI状态管理) ArkTS 通过修饰符实现组件状态与UI的自动同步,常见修饰符包括: - **`@State`**:组件内部状态,状态变更触发UI重新渲染(仅当前组件可修改)。 示例: ```typescript @Component struct MyComponent { @State count: number = 0; // 组件状态 build() { Column() { Text(`Count: ${this.count}`) Button("增加").onClick(() => { this.count++; // 修改 @State 变量触发UI更新 }) } } } ``` - **`@Link`**:双向绑定状态(与父组件的 `@State` 或 `@Link` 变量同步)。 - **`@Prop`**:单向绑定状态(子组件接收父组件传递的值,子组件修改不影响父组件)。 - **`@Provide`/`@Consume`**:跨组件状态共享(`@Provide` 提供状态,`@Consume` 在子组件中消费)。 - **`@StorageLink`**:与本地存储(如Preferences)绑定的状态(修改时自动同步到存储)。 --- ### 二、Java(鸿蒙原生开发)中的变量修饰符 鸿蒙部分原生模块(如系统服务)可能使用Java开发,其变量修饰符与标准Java一致: - **作用域与可变性**:`final`(不可变变量,类似 `const`)、`static`(静态变量)。 - **访问控制**:`public`、`private`、`protected`(默认包级访问)。 - **线程相关**:`volatile`(保证多线程可见性)、`synchronized`(同步方法/块)。 --- ### 关键总结 - **ArkTS** 中优先使用 `let`/`const` 管理变量作用域,`static`/访问控制修饰符管理类成员,响应式修饰符(如 `@State`)管理UI状态。 - **Java** 中变量修饰符与标准Java一致,侧重静态性、访问控制线程安全。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值