零基础鸿蒙应用开发第四节:运算符与运算规则

零基础鸿蒙应用开发学习计划表

【学习目标】

  1. 掌握算术、比较、逻辑、赋值、三元运算5类核心基础运算符的语法与用法
  2. 能区分 =====||?? 的核心差异,避开基础踩坑
  3. 理解自增/自减、逻辑运算符的短路特性,会用简单表达式解决问题
  4. 掌握“括号优先”的运算规则,能写出符合预期的简单表达式
  5. 掌握typeof运算符的用法,能正确检测值的类型

【学习重点】

  1. 核心用法:5类基础运算符的语法与实际应用场景
  2. 避坑要点=====||??的差异,以及如何正确选择使用
  3. 特性掌握:自增/自减的前置/后置区别、逻辑运算符的短路特性
  4. 规则应用:运算优先级(括号优先)的实际使用,确保表达式结果符合预期
  5. 类型检测typeof运算符的使用及特殊情况处理

特别说明:本节内容是变量与基本类型的延伸,所有运算符操作均基于前一节的numberstringboolean类型展开,重点关注表达式的运算逻辑与结果。

一、工程结构

本节我们将创建名为OperatorDemo的工程,基于鸿蒙5.0(API12)开发,使用DevEco Studio 6.0+工具,项目结构目录如下:

OperatorDemo
├── AppScope                 # 应用全局配置目录
├── entry                    # 主模块目录(核心业务模块)
│   ├── .preview             # 预览相关配置
│   ├── src
│   │   ├── main
│   │   │   ├── ets          # ArkTS 代码核心目录
│   │   │   │   ├── entryability       # 应用入口能力(程序启动/生命周期)
│   │   │   │   ├── pages              # 页面UI目录
│   │   │   │   │   └── Index.ets      # 核心页面(调用工具函数)
│   │   │   │   └── utils              # 工具函数目录
│   │   │   │       └── TestOperator.ets # 本节所有学习内容
│   │   │   ├── resources              # 静态资源目录
│   │   │   └── module.json5           # 模块配置文件
│   │   ├── ohosTest         # 鸿蒙端测试目录
│   │   └── test             # 单元测试目录
│   ├── build-profile.json5  # 构建配置文件
│   ├── hvigorfile.ts        # 构建脚本
│   └── oh-package.json5     # 依赖包配置文件
├── hvigor                   # 构建工具依赖
└── oh_modules               # 第三方依赖包目录

开发准备步骤

  1. 打开DevEco Studio,创建OperatorDemo项目(选择Empty Ability模板,API12/鸿蒙5.0);
  2. src/main/ets目录下右键创建utils文件夹;
  3. 选中utils文件夹,右键创建OperatorTest.ets文件(存放所有运算符);
  4. 所有业务函数统一在Index.etsaboutToAppear生命周期中调用。

二、基本算术运算符

算术运算符用于处理数值的数学运算,包括基本算术运算自增/自减运算,是最基础的运算符类型。

运算符 名称 示例 说明
+ 加法 10 + 5 数值相加/字符串拼接
- 减法 10 - 5 数值相减
* 乘法 10 * 5 数值相乘
/ 除法 10 / 5 数值相除(结果为浮点数)
% 取余(模) 10 % 3 取除法的余数

2.1 代码逻辑封装

// src/main/ets/utils/OperatorTest.ets
/**
 * 算术运算符相关逻辑:基本运算、字符串拼接、自增自减
 */
export function arithmeticOperators(): void {
  // 1. 基本算术运算
  const num1: number = 10;
  const num2: number = 3;
  console.log(`【算术运算】${num1} + ${num2} = ${num1 + num2}`); // 13
  console.log(`【算术运算】${num1} - ${num2} = ${num1 - num2}`); // 7
  console.log(`【算术运算】${num1} * ${num2} = ${num1 * num2}`); // 30
  console.log(`【算术运算】${num1} / ${num2} = ${num1 / num2}`); // 3.333...
  console.log(`【算术运算】${num1} % ${num2} = ${num1 % num2}`); // 1

  // 2. +运算符的特殊用法:字符串拼接(强类型推荐显式转换)
  const str1: string = "Hello";
  const str2: string = "ArkTS";
  console.log(`【算术运算】字符串拼接:${str1 + " " + str2}`); // Hello ArkTS
  const age: number = 20;
  const user: string = "年龄:" + age; // 隐式转换,不推荐
  console.log(`【算术运算】隐式转换拼接:${user}`); // 年龄:20
  const info: string = "年龄:" + age.toString(); // 显式转换,推荐
  console.log(`【算术运算】强类型拼接:${info}`); // 年龄:20

  // 3. 自增/自减运算
  let a: number = 5;
  console.log(`【自增运算】a++ = ${a++}`); // 先输出5,再自增(a变为6)
  console.log(`【自增运算】自增后a = ${a}`); // 6
  console.log(`【自增运算】++a = ${++a}`); // 先自增(a变为7),再输出7
  console.log(`【自增运算】自增后a = ${a}`); // 7

  let b: number = 5;
  console.log(`【自减运算】b-- = ${b--}`); // 先输出5,再自减(b变为4)
  console.log(`【自减运算】自减后b = ${b}`); // 4
  console.log(`【自减运算】--b = ${--b}`); // 先自减(b变为3),再输出3
  console.log(`【自减运算】自减后b = ${b}`); // 3
}

2.2 运行效果

【算术运算】10 + 3 = 13
【算术运算】10 - 3 = 7
【算术运算】10 * 3 = 30
【算术运算】10 / 3 = 3.3333333333333335
【算术运算】10 % 3 = 1
【算术运算】字符串拼接:Hello ArkTS
【算术运算】隐式转换拼接:年龄:20
【算术运算】强类型拼接:年龄:20
【自增运算】a++ = 5
【自增运算】自增后a = 6
【自增运算】++a = 7
【自增运算】自增后a = 7
【自减运算】b-- = 5
【自减运算】自减后b = 4
【自减运算】--b = 3
【自减运算】自减后b = 3

三、赋值运算符

赋值运算符用于将右侧的值赋给左侧的变量,包括基本赋值复合赋值(结合算术运算符)。

3.1 赋值运算符列表

运算符 名称 示例 等价于
= 基本赋值 a = 10 -
+= 加法赋值 a += 5 a = a + 5
-= 减法赋值 a -= 5 a = a - 5
*= 乘法赋值 a *= 5 a = a * 5
/= 除法赋值 a /= 5 a = a / 5
%= 取余赋值 a %= 5 a = a % 5

3.2 代码逻辑封装

// src/main/ets/utils/OperatorTest.ets
/**
 * 赋值运算符相关逻辑:基本赋值、复合赋值
 */
export function assignmentOperators(): void {
  let num: number = 10;
  console.log(`\n【赋值运算】初始num = ${num}`); // 10

  // 基本赋值
  num = 20;
  console.log(`【赋值运算】num = 20 → ${num}`); // 20

  // 复合赋值
  num += 5;
  console.log(`【赋值运算】num += 5 → ${num}`); // 25
  num -= 3;
  console.log(`【赋值运算】num -= 3 → ${num}`); // 22
  num *= 2;
  console.log(`【赋值运算】num *= 2 → ${num}`); // 44
  num /= 4;
  console.log(`【赋值运算】num /= 4 → ${num}`); // 11
  num %= 3;
  console.log(`【赋值运算】num %= 3 → ${num}`); // 2
}

3.3 运行效果

【赋值运算】初始num = 10
【赋值运算】num = 20 → 20
【赋值运算】num += 5 → 25
【赋值运算】num -= 3 → 22
【赋值运算】num *= 2 → 44
【赋值运算】num /= 4 → 11
【赋值运算】num %= 3 → 2

四、比较运算符与typeof类型检测

4.1 比较运算符(大小/相等性)

运算符 名称 示例 说明
> 大于 10 > 5 返回true
< 小于 10 < 5 返回false
>= 大于等于 10 >= 10 返回true
<= 小于等于 10 <= 5 返回false
== 松散相等(值相等) null == undefined 返回true
=== 严格相等(值+类型) null === undefined 返回false
!= 松散不相等 null != undefined 返回false
!== 严格不相等 null !== undefined 返回true

4.2 typeof类型检测

运算符 名称 示例 说明
typeof 类型检测 typeof 10 返回值的类型字符串(如numberstring

关键说明

  • typeof一元运算符(非函数),typeof null返回object(JS历史遗留问题,ArkTS/TS遵循此规则);
  • 强类型环境下,typeof常用于运行时类型校验,配合条件语句处理不同类型数值。

4.3 代码逻辑封装

// src/main/ets/utils/OperatorTest.ets
/**
 * 比较与typeof运算符相关逻辑:大小比较、类型检测、相等性比较
 */
export function comparisonAndTypeofOperators(): void {
  // 1. 大小比较运算
  const numA: number = 10;
  const numB: number = 5;
  console.log(`\n【比较运算-大小】${numA} > ${numB} → ${numA > numB}`); // true
  console.log(`【比较运算-大小】${numA} < ${numB} → ${numA < numB}`); // false
  console.log(`【比较运算-大小】${numA} >= ${numA} → ${numA >= numA}`); // true
  console.log(`【比较运算-大小】${numA} <= ${numB} → ${numA <= numB}`); // false

  // 2. typeof类型检测运算
  const n: null = null;
  const u: undefined = undefined;
  console.log(`\n【typeof运算】typeof ${numA} → ${typeof numA}`); // number
  console.log(`【typeof运算】typeof "10" → ${typeof "10"}`); // string
  console.log(`【typeof运算】typeof ${true} → ${typeof true}`); // boolean
  console.log(`【typeof运算】typeof ${n} → ${typeof n}`); // object(历史遗留问题)
  console.log(`【typeof运算】typeof ${u} → ${typeof u}`); // undefined

  // 3. 相等性比较运算
  console.log(`\n【比较运算-相等性】null == undefined → ${n == u}`); // true
  console.log(`【比较运算-相等性】null === undefined → ${n === u}`); // false
  console.log(`【比较运算-相等性】null != undefined → ${n != u}`); // false
  console.log(`【比较运算-相等性】null !== undefined → ${n !== u}`); // true
}

4.4 运行效果

【比较运算-大小】10 > 5 → true
【比较运算-大小】10 < 5 → false
【比较运算-大小】10 >= 10 → true
【比较运算-大小】10 <= 5 → false

【typeof运算】typeof 10 → number
【typeof运算】typeof "10" → string
【typeof运算】typeof true → boolean
【typeof运算】typeof null → object
【typeof运算】typeof undefined → undefined

【比较运算-相等性】null == undefined → true
【比较运算-相等性】null === undefined → false
【比较运算-相等性】null != undefined → false
【比较运算-相等性】null !== undefined → true

五、逻辑运算符

逻辑运算符用于对布尔值进行逻辑运算,重点掌握短路特性||??的核心差异。

5.1 逻辑运算符列表

运算符 名称 示例 基本说明 短路特性
&& 逻辑与 a && b 两者都为true,才返回true 若a为false,直接返回a,不再执行b(短路)
|| 逻辑或 a || b 两者有一个为true,就返回true 若a为true,直接返回a,不再执行b(短路)
! 逻辑非 !a 取反,true变false,反之亦然 无短路特性
?? 空值合并 a ?? b 若a为null/undefined,返回b 若a不为null/undefined,直接返回a,不再执行b(短路)

5.2 代码逻辑封装

// src/main/ets/utils/OperatorTest.ets
/**
 * 逻辑运算符相关逻辑:基础运算、|| vs ??、短路特性实用场景
 */
export function logicalOperators(): void {
  // 1. 逻辑与/或/非(含短路特性)
  const bool1: boolean = true;
  const bool2: boolean = false;

  console.log(`\n【逻辑运算】${bool1} && ${bool2} → ${bool1 && bool2}`); // false
  console.log(`【逻辑运算】${bool2} && ${bool1} → ${bool2 && bool1}`); // false(短路,直接返回bool2)
  console.log(`【逻辑运算】10 && 20 → ${10 && 20}`); // 20(都为真,返回最后一个)
  console.log(`【逻辑运算】0 && 20 → ${0 && 20}`); // 0(第一个为假,短路返回0)

  console.log(`【逻辑运算】${bool1} || ${bool2} → ${bool1 || bool2}`); // true(短路,直接返回bool1)
  console.log(`【逻辑运算】${bool2} || ${bool1} → ${bool2 || bool1}`); // true
  console.log(`【逻辑运算】0 || 20 → ${0 || 20}`); // 20(0是假值)
  console.log(`【逻辑运算】"" || "ArkTS" → ${"" || "ArkTS"}`); // ArkTS(""是假值)

  console.log(`【逻辑运算】!${bool1} → ${!bool1}`); // false
  console.log(`【逻辑运算】!${bool2} → ${!bool2}`); // true
  console.log(`【逻辑运算】!0 → ${!0}`); // true(0是假值)
  console.log(`【逻辑运算】!!10 → ${!!10}`); // true(双重取反还原布尔值)

  // 2. || 与 ?? 对比
  const strB: string = "";
  const n: null = null;
  const u: undefined = undefined;

  console.log(`\n【逻辑运算】0 || 20 → ${0 || 20}`); // 20(0是假值)
  console.log(`【逻辑运算】0 ?? 20 → ${0 ?? 20}`); // 0(0不是空值)
  console.log(`【逻辑运算】"" || "ArkTS" → ${"" || "ArkTS"}`); // ArkTS(""是假值)
  console.log(`【逻辑运算】"" ?? "ArkTS" → ${"" ?? "ArkTS"}`); // ""(""不是空值)
  console.log(`【逻辑运算】null ?? "ArkTS" → ${n ?? "ArkTS"}`); // ArkTS(null是空值)
  console.log(`【逻辑运算】undefined ?? "ArkTS" → ${u ?? "ArkTS"}`); // ArkTS(undefined是空值)

  // 3. 短路特性的实际应用
  console.log(`\n【逻辑运算】短路特性实用场景`);
  const hasPermission = true;
  hasPermission && console.log("✅ 执行权限相关操作"); // 条件满足,执行函数

  const userAvatar: string | null = null;
  userAvatar ?? console.log("⚠️ 用户未设置头像"); // 空值,执行提示

  // 业务场景:商品库存(0是有效数值,需保留)
  const stock = 0;
  const showStock1 = stock || "库存未知"; // 错误:0被当作假值
  const showStock2 = stock ?? "库存未知"; // 正确:保留0
  console.log(`【业务场景】stock || "库存未知" → ${showStock1}`); // 库存未知
  console.log(`【业务场景】stock ?? "库存未知" → ${showStock2}`); // 0
}

5.3 运行效果

【逻辑运算】true && false → false
【逻辑运算】false && true → false
【逻辑运算】10 && 20 → 20
【逻辑运算】0 && 20 → 0
【逻辑运算】true || false → true
【逻辑运算】false || true → true
【逻辑运算】0 || 20 → 20
【逻辑运算】"" || "ArkTS" → ArkTS
【逻辑运算】!true → false
【逻辑运算】!false → true
【逻辑运算】!0 → true
【逻辑运算】!!10 → true

【逻辑运算】0 || 20 → 20
【逻辑运算】0 ?? 20 → 0
【逻辑运算】"" || "ArkTS" → ArkTS
【逻辑运算】"" ?? "ArkTS" → ""
【逻辑运算】null ?? "ArkTS" → ArkTS
【逻辑运算】undefined ?? "ArkTS" → ArkTS

【逻辑运算】短路特性实用场景
✅ 执行权限相关操作
⚠️ 用户未设置头像
【业务场景】stock || "库存未知" → 库存未知
【业务场景】stock ?? "库存未知" → 0

六、三元运算符(条件运算符)

三元运算符是简化的if-else语句,语法为条件表达式 ? 表达式1 : 表达式2,适用于简单二选一判断。

6.1 代码逻辑封装

// src/main/ets/utils/OperatorTest.ets
/**
 * 三元运算符相关逻辑:基本用法、嵌套、实用场景
 */
export function ternaryOperators(): void {
  // 1. 基本用法(成绩及格判断)
  const score: number = 85;
  const result: string = score >= 60 ? "及格" : "不及格";
  console.log(`\n【三元运算】成绩${score} → ${result}`); // 及格

  // 2. 嵌套用法(成绩等级判断)
  const grade: string = score >= 90 ? "优秀" : (score >= 80 ? "良好" : (score >= 60 ? "及格" : "不及格"));
  console.log(`【三元运算】成绩${score} → 等级${grade}`); // 良好

  // 3. 实用场景(绝对值/库存提示)
  const numD: number = -15;
  const absNum: number = numD >= 0 ? numD : -numD;
  console.log(`【三元运算】${numD}的绝对值 → ${absNum}`); // 15

  const stockNum: number = 0;
  const stockTip: string = stockNum > 0 ? `库存充足(${stockNum}件)` : (stockNum === 0 ? "库存告急" : "库存未知");
  console.log(`【三元运算】库存提示 → ${stockTip}`); // 库存告急
}

6.2 运行效果

【三元运算】成绩85 → 及格
【三元运算】成绩85 → 等级良好
【三元运算】-15的绝对值 → 15
【三元运算】库存提示 → 库存告急

七、运算优先级与括号优先规则

当表达式中有多个运算符时,会按优先级执行,括号()拥有最高优先级,可强制改变执行顺序。

7.1 运算优先级(从高到低)

  1. 括号()
  2. 自增++/自减--、逻辑非!typeof
  3. 算术运算符(*///% > +/-
  4. 比较运算符(>/</>=/<= > ==/===/!=/!==
  5. 逻辑与&&
  6. 逻辑或||、空值合并??
  7. 三元运算符? :
  8. 赋值运算符=/+=/-=

7.2 代码逻辑封装

// src/main/ets/utils/OperatorTest.ets
/**
 * 运算优先级相关逻辑:括号优先、不同运算符优先级演示
 */
export function operatorPrecedence(): void {
  // 示例1:算术运算符优先级(* > +)
  const expr1: number = 10 + 5 * 2;
  const expr2: number = (10 + 5) * 2;
  console.log(`\n【运算优先级】10 + 5 * 2 = ${expr1}`); // 20(先乘后加)
  console.log(`【运算优先级】(10 + 5) * 2 = ${expr2}`); // 30(括号优先)

  // 示例2:比较+逻辑运算符优先级
  const x: number = 8;
  const expr3: boolean = x > 5 && x < 10;
  console.log(`【运算优先级】x > 5 && x < 10 = ${expr3}`); // true

  // 示例3:三元+赋值运算符优先级
  let y: number = 0;
  y = x > 5 ? 10 : 5; // 三元优先级高于赋值
  console.log(`【运算优先级】y = x > 5 ? 10 : 5 → ${y}`); // 10

  // 示例4:逻辑非+比较运算符优先级
  const expr5: boolean = !(10 > 5 && 3 < 2); // 括号改变顺序
  console.log(`【运算优先级】!(10 > 5 && 3 < 2) = ${expr5}`); // true
}

/**
 * 思考题:浮点数精度问题
 */
export function floatPrecisionIssue(): void {
  const num3: number = 0.2 + 0.1;
  console.log(`\n【思考题】0.2 + 0.1 = ${num3}`); // 输出:0.30000000000000004
  console.log(`【思考题说明】浮点数在二进制存储中存在精度损耗,下节将学习如何控制数值精度`);
}

7.3 运行效果

【运算优先级】10 + 5 * 2 = 20
【运算优先级】(10 + 5) * 2 = 30
【运算优先级】x > 5 && x < 10 = true
【运算优先级】x > (5 && x) < 10 = false
【运算优先级】y = x > 5 ? 10 : 5 → 10
【运算优先级】!(10 > 5 && 3 < 2) = true
【运算优先级】!10 > 5 && 3 < 2 = false

【思考题】0.2 + 0.1 = 0.30000000000000004
【思考题说明】浮点数在二进制存储中存在精度损耗,下节将学习如何控制数值精度

八、完整页面调用代码(Index.ets)

// src/main/ets/pages/Index.ets
import {
  arithmeticOperators,
  assignmentOperators,
  comparisonAndTypeofOperators,
  logicalOperators,
  ternaryOperators,
  operatorPrecedence,
  floatPrecisionIssue
} from '../utils/OperatorTest';

@Entry
@Component
struct Index {
  // 组件渲染前调用所有测试函数
  aboutToAppear(): void {
    // 1. 算术运算符
    arithmeticOperators();
    // 2. 赋值运算符
    assignmentOperators();
    // 3. 比较与typeof运算符
    comparisonAndTypeofOperators();
    // 4. 逻辑运算符
    logicalOperators();
    // 5. 三元运算符
    ternaryOperators();
    // 6. 运算优先级
    operatorPrecedence();
    // 7. 浮点数精度思考题
    floatPrecisionIssue();
  }

  build() {
    Column() {
      Text("ArkTS核心运算符与运算规则")
        .fontSize(30)
        .fontWeight(FontWeight.Bold)
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center);
  }
}

九、核心开发规范与注意事项

  1. 相等性判断:优先使用===/!==,避免==/!=的类型转换陷阱;
  2. || 与 ?? 选择:需要保留0、""、false等有效假值时用??,过滤所有假值时用||
  3. 自增/自减:尽量单独使用,避免嵌入复杂表达式,提升可读性;
  4. 复杂表达式:必须用括号()明确执行顺序,不要依赖优先级记忆;
  5. 类型转换:字符串拼接时,number转string建议显式调用toString(),避免隐式转换;
  6. typeof注意typeof null返回object是历史遗留问题,需特殊处理。

十、内容总结

  1. 核心运算符:掌握算术(含自增自减)、赋值、比较、逻辑(含??)、三元运算符的用法,以及typeof的类型检测功能;
  2. 避坑要点
    • ==(仅比数值)vs ===(比数值+类型):优先用===
    • ||(判断假值)vs ??(判断空值):根据是否保留0/""选择使用;
  3. 关键特性:逻辑运算符的短路特性可简化代码,括号()拥有最高运算优先级,浮点数存在二进制精度损耗问题;
  4. 强类型适配:运算符操作需遵循类型一致性,显式转换类型避免隐式转换问题。

十一、代码仓库

十二、下节预告

下一节学习基础数据类型的包装对象与类型转换,重点包括:

  1. 掌握NumberStringBoolean包装对象的核心特性与高频内置方法;
  2. 熟练处理nullundefined的边界场景,掌握显式类型转换技巧;
  3. 解决浮点数精度问题,完成数值计算、文本处理的基础开发需求。
posted @ 2026-01-15 15:30  鸿蒙-散修  阅读(0)  评论(0)    收藏  举报