散修带你入门鸿蒙应用开发基础第二节:运算符与表达式
ArkTS基础第二节:运算符与表达式
炼气二重天
【学习目标】
- 掌握算术、比较、逻辑、赋值、三元运算5类核心基础运算符的语法与用法
- 能区分
==与===、||与??的核心差异,避开基础踩坑 - 理解自增/自减、逻辑运算符的短路特性,会用简单表达式解决问题
- 掌握“括号优先”的运算规则,能写出符合预期的简单表达式
- 熟练完成本节独立项目的文件搭建与代码运行
【学习重点】
- 算术运算:
+(含字符串拼接)、%(判断奇偶)、++/--(循环常用) - 比较运算:同类型比较原则、
===的优先使用场景 - 逻辑运算:
&&(同时满足)、||(至少一个满足)的基础用法 - 赋值运算:
+=、-=等复合赋值的简化写法 - 三元运算:简单条件判断的简洁写法
- 避坑点:不同类型不能直接比较、一行只声明一个变量
一、新建工程项目
本节基于鸿蒙5.0(API12),采用独立项目开发(项目名OperatorDemo)。所有测试方法均统一添加到 utils/TestOperator.ets 类中,无需额外创建文件。
核心文件结构(仅需2个关键文件)
ets/
├── pages/
│ └── Index.ets(主页面,已自动创建,修改内容)
└── utils/
└── TestOperator.ets(新建,存放所有运算符测试函数)
步骤1:新建TestOperator.ets(测试工具类)
- 在
ets目录下右键新建utils文件夹; - 右键
utils文件夹 → 新建ArkTS File,命名为TestOperator.ets; - 写入基础框架(后续所有测试函数均添加到此类中):
// utils/TestOperator.ets
/**
* 运算符与表达式测试工具类,所有测试方法集中在此
*/
export class TestOperator {
/**
* 统一执行所有测试(主页面调用)
*/
static runAllTests() {
console.log("\n===== 第二节:运算符与表达式测试开始 =====");
// 后续每个测试函数写完后,仅保留当前要测试的调用,其余注释掉
}
}
步骤2:修改Index.ets(主页面)
打开自动生成的pages/Index.ets,替换为以下代码(承载UI+调用测试):
// pages/Index.ets
import { TestOperator } from '../utils/TestOperator';
@Entry
@Component
struct Index {
build() {
Column() {
Text("ArkTS运算符与表达式")
.fontSize(24)
.fontWeight(FontWeight.Bold)
.textAlign(TextAlign.Center)
.width('100%')
.margin({ top: 50 })
Text("查看Log面板查看测试结果")
.fontSize(16)
.textAlign(TextAlign.Center)
.width('100%')
.margin({ top: 20 })
}
.width('100%')
.height('100%')
}
// 页面加载时自动执行所有测试
aboutToAppear(): void {
TestOperator.runAllTests();
}
}
步骤3:运行验证环境
保存所有文件后,直接运行项目(使用已创建的模拟器/真实设备/预览模式),打开底部「Log」面板,看到“测试开始”日志即说明环境搭建成功。
核心操作规则:学习每个运算符模块时,仅在
runAllTests中调用当前模块的测试函数,之前的函数用//注释掉,专注单个知识点测试,无需关心“静态函数”概念,只看函数内代码逻辑。
二、算术运算符:处理数值计算
算术运算符是最基础的计算工具,重点掌握常用场景和特殊用法,严格遵循“一行一个变量”规范。
1.1 基础算术运算符(含字符串拼接)
操作步骤:
- 在
TestOperator类中添加testArithmeticBasic静态函数; - 在
runAllTests中调用该函数(无需其他配置)。
// utils/TestOperator.ets(完整代码片段)
export class TestOperator {
static runAllTests() {
console.log("\n===== 第二节:运算符与表达式测试开始 =====");
TestOperator.testArithmeticBasic(); // 仅启用当前测试函数
// 后续其他函数调依次添加,且要注释掉上一次的。
}
/**
* 测试基础算术运算符(+、-、*、/、%)及字符串拼接
* 规范:一行一个变量,提升可读性
*/
static testArithmeticBasic() {
console.log("\n===== 基础算术运算测试 =====");
// 1. 数值计算(一行一个变量,拒绝逗号分隔)
let num1: number = 10;
let 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.3333333333333335
console.log(`${num1} % ${num2} = ${num1 % num2}`); // 1(余数,用于判断奇偶)
// 2. 字符串拼接(+号的双重用途)
let name: string = "李四";
// 传统拼接(+号)
console.log("欢迎 " + name + " 学习ArkTS!"); // 欢迎 李四 学习ArkTS!
// 模板字符串拼接(推荐,支持动态插入变量)
console.log(`欢迎 ${name} 学习ArkTS!`); // 欢迎 李四 学习ArkTS!
// 3. 实用场景:判断奇偶(结合三元运算符)
let age: number = 23;
const parity: string = age % 2 === 0 ? "偶数" : "奇数";
console.log(`${age} 是${parity}`); // 23 是奇数
}
}
运行验证
保存代码后运行项目,在Log面板中查看“基础算术运算测试”相关日志,验证数值计算结果和字符串拼接效果是否正确。
1.2 自增(++)与自减(--)(循环常用)
操作步骤:
- 注释掉
testArithmeticBasic的调用; - 在
TestOperator类中添加testIncrementDecrement函数; - 在
runAllTests中调用该函数。
// utils/TestOperator.ets(新增函数片段)
static runAllTests() {
console.log("\n===== 第二节:运算符与表达式测试开始 =====");
// TestOperator.testArithmeticBasic(); // 注释之前的测试函数
TestOperator.testIncrementDecrement(); // 启用当前测试函数
}
/**
* 测试自增(++)与自减(--)运算符
* 核心:单独用无差异,表达式中看位置(前置先运算后取值,后置先取值后运算)
*/
static testIncrementDecrement() {
console.log("\n===== 自增自减运算测试 =====");
// 1. 单独使用(前置/后置完全一致,推荐用count++)
let count: number = 0;
count++; // 等价于 count = count + 1
console.log(`count++ 后:${count}`); // count++ 后:1
count--; // 等价于 count = count - 1
console.log(`count-- 后:${count}`); // count-- 后:0
// 2. 表达式中使用(基础阶段重点理解)
let x: number = 3;
let y: number = x++; // 步骤:先取x=3赋值给y → 再x自增为4
let z: number = ++x; // 步骤:先x自增为5 → 再取x=5赋值给z
console.log(`x=${x}, y=${y}, z=${z}`); // 输出:x=5, y=3, z=5
// 3. 循环常用场景(后置++最普遍)
console.log("循环输出0-4:");
for (let i: number = 0; i < 5; i++) { // 先判断i是否满足条件,再自增
console.log(`${i}`); // 0,1,2,3,4
}
}
运行验证
查看Log面板中“自增自减运算测试”日志,重点关注 x、y、z 的值是否符合预期,理解“前置先运算后取值,后置先取值后运算”的规则。
三、比较运算符:判断数据关系(核心是“同类型比较”)
比较运算符返回 true(成立)或 false(不成立),ArkTS是强类型语言,不同类型直接比较会编译报错,优先使用===。
/**
* 测试比较运算符(>、<、>=、<=、===、!==)及 === vs == 核心差异
* 核心:同类型比较,优先用===(严格相等)
*/
static testComparison() {
console.log("\n===== 比较运算符测试 =====");
// 声明变量(一行一个,类型明确)
const num: number = 5;
const str: string = "5";
const nul: string|null = null;
const undef: string|undefined = undefined;
// 1. 合法比较(同类型比较,编译通过)
console.log(`5 === 5(数字同类型):${num === 5}`); // true
console.log(`"a" === "str"(字符串):${"a" === str}`); // false
console.log(`"b" > "a"(字符串按Unicode排序):${"b" > "a"}`); // true
console.log(`10 >= 8(数字范围):${10 >= 8}`); // true
console.log(`null == undefined(特殊允许组合):${nul == undef}`); // true
console.log(`null === undefined(类型不同):${nul === undef}`); // false
// 2. 实战场景:表单输入验证(先转类型再比较)
const inputAge: string = "18"; // 表单输入默认是字符串
const age: number = Number(inputAge); // 转为数字类型(关键步骤)
console.log(`输入年龄是否等于18:${age === 18}`); // true
console.log(`输入年龄是否>=18:${age >= 18}`); // true
// 3. 非法比较(不同类型,编译报错,勿模仿)
console.log("\n===== 非法比较示例(编译报错)=====");
console.log("错误写法1:num == str(数字 vs 字符串)");
console.log("错误写法2:0 == ''(数字 vs 空字符串)");
console.log("结论:不同类型需先转类型,再用===比较");
}
运行验证
查看Log面板,重点关注 === 与 == 的差异,以及“先转类型再比较”的实战场景,理解“同类型比较”的核心原则。
四、逻辑运算符:组合条件判断
逻辑运算符用于组合多个比较条件,返回 true 或 false,重点掌握 &&(并且)、||(或者)的基础用法和短路特性,以及 ?? 与 || 的差异。
4.1 基础逻辑运算(&&、||、!)
static testLogic() {
// 准备测试变量(模拟用户状态)
const isLogin: boolean = true; // 模拟用户已登录
const hasPermission: boolean = false; // 模拟无操作权限
console.log("\n===== 4. 基础逻辑运算符测试 =====");
// 逻辑与(&&):两边都为true时,整体结果才为true(类似“并且”)
console.log(`5>3 且 8>6:${5 > 3 && 8 > 6}`); // true(两边都成立)
console.log(`5>3 且 8<6:${5 > 3 && 8 < 6}`); // false(右边不成立)
// 常用场景:多条件同时满足才执行(结合if语句演示,下节课详解)
if (isLogin && hasPermission) {
console.log(` 逻辑与:已登录(${isLogin}) 且 有权限(${hasPermission}) → 条件成立`);
} else {
console.log(` 逻辑与:已登录(${isLogin}) 且 有权限(${hasPermission}) → 条件不成立`);
}
// 逻辑或(||):至少一边为true时,整体结果就为true(类似“或者”)
console.log(`5>3 或 8<6:${5 > 3 || 8 < 6}`); // true(左边成立)
console.log(`5<3 或 8<6:${5 < 3 || 8 < 6}`); // false(两边都不成立)
// 常用场景:满足任一条件即可执行(如“管理员或VIP可享受优惠”)
const isAdmin: boolean = false;
const isVip: boolean = true;
console.log(`是管理员(${isAdmin}) 或 是VIP(${isVip}) → 可享优惠:${isAdmin || isVip}`); // true(VIP可享受)
// 用if语句演示:任意条件成立就执行
if (isAdmin || isVip) {
console.log(" 逻辑或:任意一个条件成立,执行此语句");
}
// 逻辑非(!):对布尔值取反(true→false,false→true)
console.log(`并非 5>3:${!(5 > 3)}`); // false(5>3是true,取反为false)
console.log(`并非 5<3:${!(5 < 3)}`); // true(5<3是false,取反为true)
// 常用场景:按钮点击状态切换(通过!取反实现“点击切换”)
let isPress: boolean = false; // 默认未点击
console.log(`按钮状态默认值:${isPress}`); // false
isPress = !isPress; // 第一次点击:取反为true(已点击)
console.log(`按钮点击第一次:${isPress}`); // true
isPress = !isPress; // 第二次点击:再次取反为false(未点击)
console.log(`按钮状态第二次:${isPress}`); // false
// 短路特性:左边已确定结果时,右边表达式不执行(优化性能)
console.log("\n===== 短路特性测试 =====");
// 逻辑与(&&)短路:左边为false时,右边不执行
console.log(`5<3 && console.log("执行方法"):${5 < 3 && console.log("执行方法")}`);
// 解析:5<3是false,整体结果已确定,右边的console.log("执行方法")不执行,输出false
// 常用场景:前置条件不满足时,不执行后续操作(如“未登录则不加载数据”)
console.log(`未登录(${!isLogin}) → 不加载数据:${!isLogin && "加载用户数据"}`); // false(未登录为false,不执行加载)
// 逻辑或(||)短路:左边为true时,右边不执行
console.log(`5>3 || console.log("执行方法"):${5 > 3 || console.log("执行方法")}`);
// 解析:5>3是true,整体结果已确定,右边的console.log("执行方法")不执行,输出true
// 常用场景:有有效值时,不使用默认值(如“用户填了昵称则不用默认名”)
const userNickname: string = "小明"; // 模拟用户已填昵称
console.log(`用户昵称:${userNickname || "游客"}`); // 输出“小明”(已有值,不使用默认名)
}
运行验证
查看Log面板,观察短路特性是否生效(右边的 console.log 未打印),理解逻辑运算符的判断规则。
4.2 空值合并运算符 ?? 与 || 的差异
/**
* 测试空值合并运算符(??)与逻辑或(||)的核心差异
* 核心:?? 仅处理null/undefined,|| 处理所有假值(0、""、false等)
*/
static testNullishCoalescing() {
console.log("\n===== ?? 与 || 差异测试 =====");
// 场景1:值为null/undefined(真正的空值)
const userName1: string | null = null;
const userName2: string | undefined = undefined;
console.log(`userName1(null)?? 匿名用户:${userName1 ?? "匿名用户"}`); // 匿名用户
console.log(`userName2(undefined)?? 匿名用户:${userName2 ?? "匿名用户"}`); // 匿名用户
// 场景2:值为空字符串/0(合法输入,非空值)
const userName3: string = ""; // 空字符串是合法输入
const userAge: number = 0; // 0是合法数值
console.log(`userName3(空字符串)?? 匿名用户:${userName3 ?? "匿名用户"}`); // 保留空字符串
console.log(`userAge(0)?? 18:${userAge ?? 18}`); // 保留0
// 对比:|| 会误处理合法假值
console.log(`userName3(空字符串)|| 匿名用户:${userName3 || "匿名用户"}`); // 误触发为匿名用户
console.log(`userAge(0)|| 18:${userAge || 18}`); // 误触发为18
console.log("结论:设置默认值优先用??,避免||误处理合法假值");
}
运行验证
查看Log面板,对比 ?? 与 || 对空字符串、0的处理差异,记住“默认值用??”的最佳实践。
五、赋值运算符:简化“运算+赋值”
赋值运算符将运算结果赋值给变量,复合赋值(+=/-= 等)是“变量=变量+运算数”的简化写法,提升代码简洁度。
/**
* 测试赋值运算符(=、+=、-=、*=、/=、%=)
* 核心:复合赋值是"运算+赋值"的简化写法
*/
static testAssignment() {
console.log("\n===== 赋值运算符测试 =====");
// 1. 基础赋值(=):初始化变量
let num: number = 10;
console.log(`初始值:num = ${num}`); // 10
// 2. 复合赋值(简化写法)
num += 5; // 等价于 num = num + 5
console.log(`num +=5 后:${num}`); // 15
num *= 2; // 等价于 num = num * 2
console.log(`num *=2 后:${num}`); // 30
num %= 7; // 等价于 num = num % 7(取余后赋值)
console.log(`num %=7 后:${num}`); // 2(30÷7=4余2)
num -= 1; // 等价于 num = num - 1
console.log(`num -=1 后:${num}`); // 1
// 3. 字符串拼接赋值(+= 同样适用)
let greeting: string = "Hello";
greeting += " "; // 等价于 greeting = greeting + " "
greeting += "ArkTS!"; // 等价于 greeting = greeting + "ArkTS!"
console.log(`字符串拼接后:${greeting}`); // Hello ArkTS!
}
运行验证
查看Log面板,验证复合赋值的结果是否与“完整写法”一致,掌握 += 既可以用于数值运算,也可以用于字符串拼接。
六、三元运算符:简单条件判断
三元运算符(condition ? exprIfTrue : exprIfFalse)是 if-else 的简化写法,适合简单二选一/三选一逻辑,核心是“条件成立取前面,不成立取后面”。
/**
* 测试三元运算符(条件 ? 成立值 : 不成立值)
* 核心:简单条件用三元,复杂条件后续用if-else
*/
static testTernary() {
console.log("\n===== 三元运算符测试 =====");
// 1. 基础用法:二选一(判断成年/未成年)
const age: number = 17;
const adultStatus: string = age >= 18 ? "成年" : "未成年";
console.log(`年龄${age}:${adultStatus}`); // 未成年
// 2. 嵌套用法:三选一(判断数字正负,最多嵌套2层)
const num: number = -3;
const numType: string = num > 0 ? "正数" : num === 0 ? "零" : "负数";
console.log(`数字${num}是:${numType}`); // 负数
// 3. 结合逻辑运算:区间判断(60-80为及格)
const score: number = 75;
const scoreDesc: string = score >= 60 && score < 80 ? "及格" : score >= 80 ? "优秀" : "不及格";
console.log(`分数${score}:${scoreDesc}`); // 及格
// 4. 结合算术运算:求两数最大值
const a: number = 10;
const b: number = 20;
const maxNum: number = a > b ? a : b;
console.log(`a=${a}, b=${b},较大值是:${maxNum}`); // 20
}
运行验证
查看Log面板,验证不同条件下三元运算符的返回结果是否正确,记住“嵌套不超过2层”的规则。
七、表达式与运算优先级
运算符组合形成表达式,运算优先级决定执行顺序,核心原则:不确定就加括号 (),既安全又易读。
/**
* 测试表达式与运算优先级
* 优先级从高到低:括号() → 算术(*、/、%)→ 算术(+、-)→ 比较 → 逻辑 → 三元 → 赋值
*/
static testExpressionPriority() {
console.log("\n===== 表达式与运算优先级测试 =====");
// 1. 括号改变优先级(括号优先级最高)
console.log(`10 + 20 * 2 = ${10 + 20 * 2}`); // 50(先乘后加,默认优先级)
console.log(`(10 + 20) * 2 = ${(10 + 20) * 2}`); // 60(括号优先,先加后乘)
// 2. 比较+逻辑运算(先比较,后逻辑)
const logicRes: boolean = 10 + 5 > 12 && 3 < 5;
console.log(`10 + 5 > 12 && 3 < 5 = ${logicRes}`); // true(步骤:15>12→true,3<5→true,true&&true→true)
// 3. 三元+算术运算(先算术/比较,后三元)
const ternaryRes: number = 10 > 5 ? 20 * 3 : 10 / 2;
console.log(`10>5 ? 20*3 : 10/2 = ${ternaryRes}`); // 60(先判断10>5,再计算20*3)
// 4. 复杂表达式(结合多种运算符)
const x: number = 5;
const y: number = 3;
const complexRes: number = (x + y) * 2 - 8 / 4;
console.log(`(5+3)*2 - 8/4 = ${complexRes}`); // 14(步骤:8*2=16 → 8/4=2 → 16-2=14)
console.log("结论:不确定优先级就加括号,避免逻辑错误");
}
运行验证
查看Log面板,对比有无括号的运算结果差异,理解“括号改变优先级”的核心作用,记住简化优先级顺序:算术运算 > 比较运算 > 逻辑运算 > 三元运算 > 赋值运算。
八、完整测试(可选)
所有模块学习完成后,可取消所有注释,一次性运行所有测试函数,验证整体逻辑:
// utils/TestOperator.ets(完整运行配置)
static runAllTests() {
console.log("\n===== 第二节:运算符与表达式测试开始 =====");
TestOperator.testArithmeticBasic();
TestOperator.testIncrementDecrement();
TestOperator.testComparison();
TestOperator.testLogic();
TestOperator.testNullishCoalescing();
TestOperator.testAssignment();
TestOperator.testTernary();
TestOperator.testExpressionPriority();
console.log("===== 第二节:运算符与表达式测试结束 =====");
}
【课堂小结】
- 编码规范:严格遵循“一行一个变量”,拒绝逗号分隔声明;
- 核心运算符:
- 算术运算:
%判奇偶,++/--注意表达式中位置; - 比较运算:同类型比较,优先用
===; - 逻辑运算:
&&、||支持短路,默认值用??; - 赋值运算:复合赋值简化代码,
+=通用字符串/数值; - 三元运算:简单逻辑简化写法,嵌套不超过2层;
- 算术运算:
- 避坑重点:不同类型不直接比较、不确定优先级就加括号。
【课后练习】
- 操作题:在
TestOperator中添加testDivideAndRemainder方法,声明x=15(一行一个变量),计算除以4的商(向下取整)和余数,用模板字符串打印“15除以4,商=3,余数=3”。 - 操作题:添加
testRangeCheck方法,声明num=73,用三元运算符判断是否在1-100之间,打印“73在1-100之间”或“73超出1-100范围”。 - 分析题:在
testIncrementAnalysis方法中执行let a=3; let b=++a + a++;,打印a和b的值并解释执行过程。 - 操作题:添加
testDefaultValue方法,声明score: number | null = 0和score2: number | null = null(一行一个变量),分别用??和||设置默认值60,打印4个结果并说明差异。 - 操作题:添加
testNumberProcess方法,声明num=-8,用三元运算符判断是否为正数,是则返回平方(num*num),否则返回绝对值(Math.abs(num))并打印。 - 改错题:添加
testFixError方法,修复以下代码并说明错误原因:let num: number = 5, str: string = "5"; // 错误1 console.log(num == str); // 错误2
【代码仓库】
第二节项目代码(OperatorDemo)已同步:https://gitee.com/juhetianxia321/harmony-os-code-base.git
【下节预告】
第三节将进入流程控制核心章节,系统学习程序的“决策与重复”能力:重点掌握if-else分支、if-else if-else多分支、switch-case固定值匹配的语法与场景差异;深入理解for(已知次数)、for...of(简洁遍历)、while/do-while(条件驱动)的核心用法,以及break(终止循环)与continue(跳过当前轮)的流程控制技巧;同时结合猜数字游戏、杨辉三角、99乘法表等实战案例,强化逻辑思维,让你能独立用流程控制解决复杂重复或多条件判断问题。
鸿蒙开发者学习与认证指引
(一)、官方学习班级报名(免费)
- 班级链接:HarmonyOS赋能资源丰富度建设(第四期)
- 学号填写规则:填写个人手机号码即可完成班级信息登记
(二)、HarmonyOS应用开发者认证考试(免费)
-
考试链接:HarmonyOS开发者能力认证入口
-
认证等级及适配人群
- 基础认证:适配软件工程师、移动应用开发人员,需掌握HarmonyOS基础概念、DevEco Studio基础使用、ArkTS及ArkUI基础开发等能力;
- 高级认证:适配项目经理、工程架构师,需掌握系统核心技术理念、应用架构设计、关键技术开发及应用上架运维等能力;
- 专家认证:适配研发经理、解决方案专家,需掌握分布式技术原理、端云一体化开发、跨端迁移及性能优化等高级能力。
-
认证权益:通过认证可获得电子版证书以及其他专属权益。
浙公网安备 33010602011771号