零基础鸿蒙应用开发第五节:基础数据类型对象与类型转换
【学习目标】
- 理解原始值与内置对象的核心区别,掌握
Number、String、Boolean内置对象的初始化方式 - 熟练使用内置对象的高频内置方法(数值格式化、字符串截取/查找、布尔值转换)解决实际问题
- 掌握强类型环境下的显式类型转换技巧(数值↔字符串、数值↔布尔、字符串↔布尔)
- 能处理
null/undefined的边界场景,避免转换时出现异常 - 理解内置对象的装箱/拆箱特性,明确ArkTS强类型下需显式拆箱的通用规则
【学习重点】
- 核心区别:原始值(
number/string/boolean)与内置对象(Number/String/Boolean)的本质差异 - 方法使用:内置对象的高频内置方法(如
toFixed、slice、includes)的语法与场景 - 类型转换:显式转换的多种实现方式(推荐方法+避坑方案)
- 边界处理:
null/undefined参与转换时的安全处理策略 - 强类型拆箱:ArkTS需显式调用
valueOf()拆箱后,才能将内置对象与原始值运算 - 实战应用:结合内置对象与类型转换完成数值计算、文本处理的基础需求
一、工程结构
本节我们将创建名为WrapperTypeConvertDemo的工程,基于鸿蒙5.0(API12)开发,使用DevEco Studio 6.0+工具,项目结构目录如下:
WrapperTypeConvertDemo
├── AppScope # 应用全局配置
├── entry # 主模块目录
│ ├── src
│ │ ├── main
│ │ │ ├── ets # ArkTS核心代码目录
│ │ │ │ ├── entryability # 应用入口能力
│ │ │ │ ├── pages # 页面组件目录
│ │ │ │ │ └── Index.ets # 核心页面(调用工具函数)
│ │ │ │ └── utils # 工具函数目录
│ │ │ │ └── WrapperTypeConvertTest.ets # 本节所有学习内容
│ │ │ ├── resources # 静态资源(图片/字符串等)
│ │ │ └── module.json5 # 模块配置文件
│ │ ├── ohosTest # 鸿蒙端测试目录
│ │ └── test # 单元测试目录
│ ├── build-profile.json5 # 构建配置
│ ├── hvigorfile.ts # 构建脚本
│ └── oh-package.json5 # 依赖配置
├── hvigor # 构建工具依赖
└── oh_modules # 第三方依赖包
开发准备步骤
- 打开DevEco Studio,创建
WrapperTypeConvertDemo项目(选择Empty Ability模板,API12/鸿蒙5.0); - 在
src/main/ets目录下右键创建utils文件夹; - 选中
utils文件夹,右键创建WrapperTypeConvertTest.ets文件(封装所有学习内容); - 所有学习函数在
Index.ets的aboutToAppear生命周期中统一调用。
二、原始值与内置对象的核心概念
1.1 核心区别
| 类型 | 本质 | 示例 | 特性 |
|---|---|---|---|
| 原始值 | 基本数据类型的直接值 | const num = 10 |
不可变、本身无属性/方法(但可临时调用内置对象方法,因自动装箱为包装对象) |
| 内置对象 | 引用类型的实例对象 | const numObj = new Number(10) |
可变、有属性/方法 |
1.2 装箱与拆箱
- 装箱:分为「自动装箱」和「手动装箱」
- 自动装箱:当原始值调用内置对象的方法时,ArkTS会自动创建对应的内置对象,方法执行后销毁该对象(如
10.toString()); - 手动装箱:通过
new Number(10)/new String("ArkTS")创建内置对象(不推荐,仅用于演示)。
- 自动装箱:当原始值调用内置对象的方法时,ArkTS会自动创建对应的内置对象,方法执行后销毁该对象(如
- 拆箱:调用内置对象的
valueOf()方法获取原始值,才能与对应原始值运算:- ✅ 正确:
numObj.valueOf() + 5(先拆箱再运算); - ❌ 错误:
numObj + 5(类型不一致,编译报错)。
- ✅ 正确:
- 开发建议:优先使用原始值,仅在需要调用内置对象方法时依赖自动装箱,禁止手动创建内置对象(冗余且性能低)。
1.3 代码封装:原始值与内置对象的区别
// src/main/ets/utils/WrapperTypeConvertTest.ets
/**
* 学习原始值与内置对象的核心区别、装箱与拆箱特性
*/
export function testPrimitiveAndWrapper(): void {
// 1. 原始值(推荐使用)
const numPrimitive: number = 10;
const strPrimitive: string = "ArkTS";
const boolPrimitive: boolean = true;
console.log(`【原始值】类型检测:${typeof numPrimitive} → ${numPrimitive}`); // number → 10
console.log(`【原始值】类型检测:${typeof strPrimitive} → ${strPrimitive}`); // string → ArkTS
console.log(`【原始值】类型检测:${typeof boolPrimitive} → ${boolPrimitive}`); // boolean → true
// 2. 内置对象(不推荐手动创建,仅演示)
const numObj: Number = new Number(10);
const strObj: String = new String("ArkTS");
const boolObj: Boolean = new Boolean(true);
console.log(`\n【内置对象】类型检测:${typeof numObj} → ${numObj}`); // object → 10
console.log(`【内置对象】类型检测:${typeof strObj} → ${strObj}`); // object → ArkTS
console.log(`【内置对象】类型检测:${typeof boolObj} → ${boolObj}`); // object → true
// 3. 自动装箱:原始值调用内置对象方法
const numStr: string = numPrimitive.toString(); // 自动创建Number对象
console.log(`\n【自动装箱】10.toString() → ${numStr}(类型:${typeof numStr})`); // 10 → string
// 4. 显式拆箱
const sum: number = numObj.valueOf() + 5;
console.log(`【显式拆箱】numObj.valueOf() + 5 → ${sum}(类型:${typeof sum})`); // 15 → number
}
1.4 运行效果
【原始值】类型检测:number → 10
【原始值】类型检测:string → ArkTS
【原始值】类型检测:boolean → true
【内置对象】类型检测:object → 10
【内置对象】类型检测:object → ArkTS
【内置对象】类型检测:object → true
【自动装箱】10.toString() → 10(类型:string)
【显式拆箱】numObj.valueOf() + 5 → 15(类型:number)
三、Number内置对象的高频内置方法
Number内置对象的方法主要用于数值格式化、数值判断,原始值可通过自动装箱调用这些方法。
3.1高频方法列表
| 方法名 | 作用 | 示例 | 结果 |
|---|---|---|---|
toString(base) |
将数值转为字符串,base为进制(2-36,默认10) |
10.toString(2) |
"1010" |
toFixed(digits) |
保留指定小数位数(四舍五入),digits为小数位数(0-20) |
3.14159.toFixed(2) |
"3.14" |
toPrecision(len) |
保留指定有效数字(四舍五入),len为有效数字位数(1-21) |
123.45.toPrecision(3) |
"123" |
Number.parseInt(str, base) |
全局方法:将字符串转为整数(进制可选) | Number.parseInt("123a") |
123 |
Number.parseFloat(str) |
全局方法:将字符串转为浮点数 | Number.parseFloat("123.45a") |
123.45 |
Number.isInteger(num) |
静态方法:判断是否为整数 | Number.isInteger(10.0) |
true |
Number.isNaN(num) |
静态方法:判断是否为NaN(仅对NaN返回true) | Number.isNaN(10/0) |
false(Infinity不是NaN) |
valueOf() |
显式拆箱:获取Number对象对应的原始数值 | new Number(10).valueOf() |
10 |
3.2 代码封装:Number内置对象的方法
// src/main/ets/utils/WrapperTypeConvertTest.ets
/**
* 学习Number内置对象的高频内置方法(数值格式化、字符串转数值、数值判断)
* 新手避坑:toFixed返回字符串,运算前需转数值
*/
export function testNumberWrapperMethods(): void {
console.log(`\n========== Number内置对象方法 ==========`);
const num: number = 3.1415926;
const intNum: number = 100;
const strNum: string = "123.456a";
const numObj: Number = new Number(99.9); // 仅用于演示拆箱
// 1. 数值格式化(高频)
console.log(`【数值格式化】${num}.toFixed(2) → ${num.toFixed(2)}`); // 3.14(保留2位小数)
console.log(`【数值格式化】${num}.toFixed(4) → ${num.toFixed(4)}`); // 3.1416(四舍五入)
console.log(`【数值格式化】${num}.toPrecision(3) → ${num.toPrecision(3)}`); // 3.14(保留3位有效数字)
console.log(`【数值格式化】${intNum}.toString(2) → ${intNum.toString(2)}`); // 1100100(二进制)
console.log(`【数值格式化】${intNum}.toString(16) → ${intNum.toString(16)}`); // 64(十六进制)
// 新手错误示例:toFixed返回字符串,直接运算会出错
const price = 2999;
const wrongTotal = price.toFixed(2) + 10; // "2999.0010"(非数值运算)
const correctTotal = Number(price.toFixed(2)) + 10; // 3009.00
console.log(`\n【错误示例】toFixed直接运算 → ${wrongTotal}`);
console.log(`【正确写法】toFixed转数值后运算 → ${correctTotal}`);
// 2. 字符串转数值(全局方法)
console.log(`\n【字符串转数值】Number.parseInt("${strNum}") → ${Number.parseInt(strNum)}`); // 123
console.log(`【字符串转数值】Number.parseFloat("${strNum}") → ${Number.parseFloat(strNum)}`); // 123.456
console.log(`【字符串转数值】Number.parseInt("1010", 2) → ${Number.parseInt("1010", 2)}`); // 10(二进制转十进制)
// 3. 数值判断(静态方法)
console.log(`\n【数值判断】Number.isInteger(10) → ${Number.isInteger(10)}`); // true
console.log(`【数值判断】Number.isInteger(10.5) → ${Number.isInteger(10.5)}`); // false
console.log(`【数值判断】Number.isNaN(NaN) → ${Number.isNaN(NaN)}`); // true
console.log(`【数值判断】Number.isNaN(10/0) → ${Number.isNaN(10/0)}`); // false(Infinity不是NaN)
// 4. 显式拆箱示例
console.log(`\n【显式拆箱】numObj.valueOf() + 0.1 → ${numObj.valueOf() + 0.1}`); // 100.0
}
3.3 运行效果
========== Number内置对象方法 ==========
【数值格式化】3.1415926.toFixed(2) → 3.14
【数值格式化】3.1415926.toFixed(4) → 3.1416
【数值格式化】3.1415926.toPrecision(3) → 3.14
【数值格式化】100.toString(2) → 1100100
【数值格式化】100.toString(16) → 64
【错误示例】toFixed直接运算 → 2999.0010
【正确写法】toFixed转数值后运算 → 3009
【字符串转数值】Number.parseInt("123.456a") → 123
【字符串转数值】Number.parseFloat("123.456a") → 123.456
【字符串转数值】Number.parseInt("1010", 2) → 10
【数值判断】Number.isInteger(10) → true
【数值判断】Number.isInteger(10.5) → false
【数值判断】Number.isNaN(NaN) → true
【数值判断】Number.isNaN(10/0) → false
【显式拆箱】numObj.valueOf() + 0.1 → 100.0
四、String内置对象的高频内置方法
String内置对象的方法是文本处理的核心,涵盖字符串截取、查找、替换、大小写转换等场景,原始值可通过自动装箱调用。
4.1 高频方法列表
| 方法名 | 作用 | 示例 | 结果 |
|---|---|---|---|
length(属性) |
获取字符串长度 | "ArkTS".length |
5 |
charAt(index) |
获取指定索引的字符(索引从0开始) | "ArkTS".charAt(2) |
"k" |
slice(start, end) |
截取字符串(start起始索引,end结束索引(不包含),支持负数) | "ArkTS".slice(1, 3) |
"rk" |
substring(start, end) |
截取字符串(与slice类似,不支持负数,start>end时自动交换) | "ArkTS".substring(3, 1) |
"rk" |
includes(substr) |
判断是否包含子字符串(返回布尔值) | "ArkTS".includes("TS") |
true |
indexOf(substr) |
查找子字符串首次出现的索引(未找到返回-1) | "ArkTS".indexOf("k") |
2 |
lastIndexOf(substr) |
查找子字符串最后出现的索引(未找到返回-1) | "ArkTSArkTS".lastIndexOf("k") |
7 |
toUpperCase() |
转为大写字符串 | "ArkTS".toUpperCase() |
"ARKTS" |
toLowerCase() |
转为小写字符串 | "ArkTS".toLowerCase() |
"arkts" |
trim() |
去除首尾空格(含换行符、制表符) | " ArkTS ".trim() |
"ArkTS" |
replace(old, new) |
替换第一个匹配的子字符串(支持正则) | "ArkTS ArkTS".replace("TS", "JS") |
"ArkJS ArkTS" |
split(sep) |
按分隔符分割为数组 | "a,b,c".split(",") |
["a","b","c"] |
valueOf() |
显式拆箱:获取String对象对应的原始字符串 | new String("ArkTS").valueOf() |
"ArkTS" |
4.2 代码封装:String内置对象的方法
// src/main/ets/utils/WrapperTypeConvertTest.ets
/**
* 学习String内置对象的高频内置方法(文本处理核心)
* 新手避坑:1. slice支持负数索引,优先使用;2. 索引越界返回空字符串,无报错
*/
export function testStringWrapperMethods(): void {
console.log(`\n========== String内置对象方法 ==========`);
const str: string = " Hello ArkTS! ";
const simpleStr: string = "ArkTS";
const strObj: String = new String("Test"); // 仅用于演示拆箱
// 1. 基础属性与字符获取(高频)
console.log(`【基础属性】"${simpleStr}".length → ${simpleStr.length}`); // 5
console.log(`【字符获取】"${simpleStr}".charAt(2) → ${simpleStr.charAt(2)}`); // k(偶尔用)
console.log(`【字符获取】"${simpleStr}"[2] → ${simpleStr[2]}`); // k(简化写法,推荐)
// 新手错误示例:索引越界
console.log(`\n【错误示例】charAt越界 → ${simpleStr.charAt(10)}`); // ""(无报错,返回空字符串)
console.log(`【错误示例】slice越界 → ${simpleStr.slice(10)}`); // ""(无报错,返回空字符串)
// 2. 字符串截取(高频)
console.log(`\n【字符串截取】"${simpleStr}".slice(1, 3) → ${simpleStr.slice(1, 3)}`); // rk
console.log(`【字符串截取】"${simpleStr}".slice(-2) → ${simpleStr.slice(-2)}`); // TS(倒数2个字符,推荐)
console.log(`【字符串截取】"${simpleStr}".substring(3, 1) → ${simpleStr.substring(3, 1)}`); // rk(不推荐,无负数索引)
// 3. 字符串查找(高频)
console.log(`\n【字符串查找】"${simpleStr}".includes("TS") → ${simpleStr.includes("TS")}`); // true
console.log(`【字符串查找】"${simpleStr}".indexOf("k") → ${simpleStr.indexOf("k")}`); // 2
console.log(`【字符串查找】"${simpleStr}".indexOf("JS") → ${simpleStr.indexOf("JS")}`); // -1(未找到)
// 4. 大小写转换与去空格(高频)
console.log(`\n【大小写转换】"${simpleStr}".toUpperCase() → ${simpleStr.toUpperCase()}`); // ARKTS
console.log(`【大小写转换】"${simpleStr}".toLowerCase() → ${simpleStr.toLowerCase()}`); // arkts
console.log(`【去空格】"${str}".trim() → "${str.trim()}"`); // Hello ArkTS!
// 5. 替换与分割(高频)
console.log(`\n【字符串替换】"ArkTS ArkTS".replace("TS", "JS") → ${"ArkTS ArkTS".replace("TS", "JS")}`); // ArkJS ArkTS
console.log(`【字符串分割】"a,b,c".split(",") → ${JSON.stringify("a,b,c".split(","))}`); // ["a","b","c"]
console.log(`【字符串分割】"a|b|c".split("|") → ${JSON.stringify("a|b|c".split("|"))}`); // ["a","b","c"]
// 6. 显式拆箱示例
console.log(`\n【显式拆箱】strObj.valueOf() + "123" → ${strObj.valueOf() + "123"}`); // Test123
}
4.3 运行效果
========== String内置对象方法 ==========
【基础属性】"ArkTS".length → 5
【字符获取】"ArkTS".charAt(2) → k
【字符获取】"ArkTS"[2] → k
【错误示例】charAt越界 →
【错误示例】slice越界 →
【字符串截取】"ArkTS".slice(1, 3) → rk
【字符串截取】"ArkTS".slice(-2) → TS
【字符串截取】"ArkTS".substring(3, 1) → rk
【字符串查找】"ArkTS".includes("TS") → true
【字符串查找】"ArkTS".indexOf("k") → 2
【字符串查找】"ArkTS".indexOf("JS") → -1
【大小写转换】"ArkTS".toUpperCase() → ARKTS
【大小写转换】"ArkTS".toLowerCase() → arkts
【去空格】" Hello ArkTS! ".trim() → "Hello ArkTS!"
【字符串替换】"ArkTS ArkTS".replace("TS", "JS") → ArkJS ArkTS
【字符串分割】"a,b,c".split(",") → ["a","b","c"]
【字符串分割】"a|b|c".split("|") → ["a","b","c"]
【显式拆箱】strObj.valueOf() + "123" → Test123
五、Boolean内置对象的核心方法
Boolean内置对象的方法较少,核心作用是将其他类型值转为布尔值,常用Boolean()全局函数(而非手动创建内置对象)。
5.1 布尔值转换规则
| 值示例 | 类型 | 转换结果 | 新手易错点 |
|---|---|---|---|
| 0 | number | false | - |
| 10 | number | true | - |
| "" | string | false | - |
| "0" | string | true | 误以为和数值0一样是false |
| "false" | string | true | 误以为内容是false就转false |
| null | null | false | - |
| undefined | undefined | false | - |
| [] | array | true | 空数组不是false |
| NaN | number | false | NaN是特殊的falsy值 |
| Infinity | number | true | 无穷大不是false |
5.2 核心方法
| 方法名 | 作用 | 示例 | 结果 |
|---|---|---|---|
valueOf() |
显式拆箱:获取Boolean对象对应的原始布尔值 | new Boolean(true).valueOf() |
true |
5.3 代码封装:Boolean内置对象与布尔值转换
// src/main/ets/utils/WrapperTypeConvertTest.ets
/**
* 学习Boolean内置对象的核心方法与布尔值转换规则
* 新手避坑:1. 空数组/空对象转布尔为true;2. "0"转布尔为true;3. !!与Boolean()效果一致
*/
export function testBooleanWrapperMethods(): void {
console.log(`\n========== Boolean内置对象与转换 ==========`);
const bool: boolean = false;
const boolObj: Boolean = new Boolean(true); // 仅用于演示拆箱
// 1. 内置对象方法(极少使用)
console.log(`【Boolean方法】${bool}.toString() → ${bool.toString()}`); // false
console.log(`【Boolean方法】${!bool}.toString() → ${(!bool).toString()}`); // true
// 2. 其他类型转布尔值(推荐使用Boolean()全局函数)
console.log(`\n【布尔转换】Boolean(0) → ${Boolean(0)}`); // false | 数值0是falsy值
console.log(`【布尔转换】Boolean(10) → ${Boolean(10)}`); // true | 非0数值是truthy值
console.log(`【布尔转换】Boolean("") → ${Boolean("")}`); // false | 空字符串是falsy值
console.log(`【布尔转换】Boolean("0") → ${Boolean("0")}`); // true | 非空字符串(新手高频坑)
console.log(`【布尔转换】Boolean("false") → ${Boolean("false")}`); // true | 非空字符串(新手高频坑)
console.log(`【布尔转换】Boolean(null) → ${Boolean(null)}`); // false | null是falsy值
console.log(`【布尔转换】Boolean(undefined) → ${Boolean(undefined)}`); // false | undefined是falsy值
console.log(`【布尔转换】Boolean([]) → ${Boolean([])}`); // true | 空数组是truthy值(新手高频坑)
// 3. 双重取反(!!)快速转布尔值
console.log(`\n【双重取反】!!0 → ${!!0}`); // false | 等价于Boolean(0)
console.log(`【双重取反】!!"ArkTS" → ${!!"ArkTS"}`); // true | 等价于Boolean("ArkTS")
console.log(`【双重取反】!!null → ${!!null}`); // false | 等价于Boolean(null)
// 4. 显式拆箱示例
console.log(`\n【显式拆箱】boolObj.valueOf() && false → ${boolObj.valueOf() && false}`); // false
}
5.4 运行效果
========== Boolean内置对象与转换 ==========
【Boolean方法】false.toString() → false
【Boolean方法】true.toString() → true
【布尔转换】Boolean(0) → false
【布尔转换】Boolean(10) → true
【布尔转换】Boolean("") → false
【布尔转换】Boolean("0") → true
【布尔转换】Boolean("false") → true
【布尔转换】Boolean(null) → false
【布尔转换】Boolean(undefined) → false
【布尔转换】Boolean([]) → true
【双重取反】!!0 → false
【双重取反】!!"ArkTS" → true
【双重取反】!!null → false
【显式拆箱】boolObj.valueOf() && false → false
六、强类型环境下的显式类型转换
ArkTS均禁止隐式类型转换,所有类型转换必须显式进行,以下是常用类型的转换方法(推荐方案+避坑方案)。
(一)数值与字符串的相互转换
1. 数值转字符串(2种推荐方法)
- 方法1:
num.toString()(原始值自动装箱) - 方法2:
String(num)(处理null/undefined时更安全)
2. 字符串转数值(2种推荐方法)
- 方法1:
Number(str)(严格转换,非数值字符串返回NaN) - 方法2:
Number.parseInt(str)/Number.parseFloat(str)(宽松转换,截取数字部分)
代码逻辑封装:数值↔字符串转换
// src/main/ets/utils/WrapperTypeConvertTest.ets
/**
* 学习数值与字符串的显式类型转换(强类型环境推荐方案)
*/
export function testNumberStringConversion(): void {
console.log(`\n========== 数值↔字符串转换 ==========`);
const num1: number = 123;
const str1: string = "456";
const str2: string = "789a";
const str3: string = "abc";
// 1. 数值转字符串
const numToStr1: string = num1.toString();
const numToStr2: string = String(num1);
console.log(`【数值转字符串】${num1}.toString() → ${numToStr1}(类型:${typeof numToStr1})`); // 123 → string
console.log(`【数值转字符串】String(${num1}) → ${numToStr2}(类型:${typeof numToStr2})`); // 123 → string
// 2. 字符串转数值
const strToNum1: number = Number(str1);
const strToNum2: number = Number.parseInt(str2);
const strToNum3: number = Number(str3);
console.log(`\n【字符串转数值】Number("${str1}") → ${strToNum1}(类型:${typeof strToNum1})`); // 456 → number
console.log(`【字符串转数值】Number.parseInt("${str2}") → ${strToNum2}(类型:${typeof strToNum2})`); // 789 → number
console.log(`【字符串转数值】Number("${str3}") → ${strToNum3}(类型:${typeof strToNum3})`); // NaN → number
}
运行效果
========== 数值↔字符串转换 ==========
【数值转字符串】123.toString() → 123(类型:string)
【数值转字符串】String(123) → 123(类型:string)
【字符串转数值】Number("456") → 456(类型:number)
【字符串转数值】Number.parseInt("789a") → 789(类型:number)
【字符串转数值】Number("abc") → NaN(类型:number)
(二)数值/字符串与布尔值的相互转换
1. 数值/字符串转布尔值(2种推荐方法)
- 方法1:
Boolean(value)(遵循布尔转换规则) - 方法2:
!!value(简化写法,效果与Boolean()一致)
2. 布尔值转数值/字符串(直接转换)
- 布尔值转数值:
Number(bool)(true→1,false→0) - 布尔值转字符串:
bool.toString()(true→"true",false→"false")
代码逻辑封装:数值/字符串↔布尔值转换
// src/main/ets/utils/WrapperTypeConvertTest.ets
/**
* 学习数值/字符串与布尔值的显式类型转换
*/
export function testBooleanConversion(): void {
console.log(`\n========== 数值/字符串↔布尔值转换 ==========`);
const num2: number = 0;
const num3: number = 10;
const str4: string = "";
const str5: string = "false";
const bool2: boolean = true;
// 1. 数值/字符串转布尔值
console.log(`【数值转布尔】Boolean(${num2}) → ${Boolean(num2)}`); // false
console.log(`【数值转布尔】!!${num3} → ${!!num3}`); // true
console.log(`【字符串转布尔】Boolean("${str4}") → ${Boolean(str4)}`); // false
console.log(`【字符串转布尔】!!"${str5}" → ${!!str5}`); // true
// 2. 布尔值转数值/字符串
console.log(`\n【布尔转数值】Number(${bool2}) → ${Number(bool2)}`); // 1
console.log(`【布尔转数值】Number(${!bool2}) → ${Number(!bool2)}`); // 0
console.log(`【布尔转字符串】${bool2}.toString() → ${bool2.toString()}`); // true
console.log(`【布尔转字符串】String(${!bool2}) → ${String(!bool2)}`); // false
}
运行效果
========== 数值/字符串↔布尔值转换 ==========
【数值转布尔】Boolean(0) → false
【数值转布尔】!!10 → true
【字符串转布尔】Boolean("") → false
【字符串转布尔】!!"false" → true
【布尔转数值】Number(true) → 1
【布尔转数值】Number(false) → 0
【布尔转字符串】true.toString() → true
【布尔转字符串】String(false) → false
(三)null/undefined的安全转换处理
null/undefined无法直接转换为数值/字符串(会报错或返回"null"/"undefined"),需先进行空值判断再转换。
关键区别:
??(空值合并运算符)仅对null/undefined生效,||(逻辑或)对所有falsy值生效,鸿蒙开发中优先用??。
代码逻辑封装:null/undefined的安全转换
// src/main/ets/utils/WrapperTypeConvertTest.ets
/**
* 学习null/undefined的安全转换处理(避免转换异常)
* 核心避坑:?? 仅处理null/undefined,|| 处理所有falsy值(数值型默认值慎用||)
*/
export function testNullUndefinedSafeConversion(): void {
console.log(`\n========== null/undefined的安全转换 ==========`);
const nullVar: string | null = null;
const undefVar: number | undefined = undefined;
const age: number = 0; // 合法数值(falsy值)
// 1. 错误示例:直接转换(不推荐)
console.log(`【错误示例】String(null) → ${String(nullVar)}`); // null
console.log(`【错误示例】Number(undefined) → ${Number(undefVar)}`); // NaN
// 2. 正确示例:空值判断后转换(推荐)
const nullToStr: string = nullVar ?? "";
console.log(`\n【安全转换】null ?? "" → "${nullToStr}"`); // ""
const undefToNum: number = undefVar ?? 0;
console.log(`【安全转换】undefined ?? 0 → ${undefToNum}`); // 0
// 关键区别:?? vs ||
console.log(`【对比】age ?? 18 → ${age ?? 18}`); // 0(保留合法0值,推荐)
console.log(`【对比】age || 18 → ${age || 18}`); // 18(误判0为无效值,慎用)
const userAge: number | undefined = undefined;
const ageStr: string = String(userAge ?? 18);
console.log(`【安全转换】String(undefined ?? 18) → ${ageStr}`); // 18
}
运行效果
========== null/undefined的安全转换 ==========
【错误示例】String(null) → null
【错误示例】Number(undefined) → NaN
【安全转换】null ?? "" → ""
【安全转换】undefined ?? 0 → 0
【对比】age ?? 18 → 0
【对比】age || 18 → 18
【安全转换】String(undefined ?? 18) → 18
七、实战练习:结合内置对象与类型转换处理业务场景
练习目标
整合内置对象方法、类型转换、空值处理的技巧,完成鸿蒙端常见业务场景处理。
代码逻辑封装:实战练习
// src/main/ets/utils/WrapperTypeConvertTest.ets
/**
* 实战练习:结合内置对象与类型转换处理鸿蒙端常见业务场景
*/
export function testPracticalScenario(): void {
console.log(`\n========== 实战练习 ==========`);
// 场景1:商品价格格式化(保留2位小数,补0)
const price: number = 2999;
const priceStr: string = price.toFixed(2);
console.log(`【场景1】商品价格:${price} → 格式化后:${priceStr}元`); // 2999.00元
// 场景2:用户输入手机号处理(截取后4位,隐藏前7位)
const phone: string = "13812345678";
const phoneHide: string = phone.slice(0, 3) + "****" + phone.slice(7);
console.log(`【场景2】手机号:${phone} → 隐藏后:${phoneHide}`); // 138****5678
// 场景3:用户输入年龄处理(字符串转数值,判断是否成年)
const ageInput: string = "24a";
// 处理非数字输入时返回0,避免Number.parseInt返回NaN导致后续判断异常
const age: number = isNaN(Number.parseInt(ageInput)) ? 0 : Number.parseInt(ageInput);
const isAdult: boolean = age >= 18;
console.log(`【场景3】输入年龄:${ageInput} → 转换后:${age} → 是否成年:${isAdult}`); // 24 → true
// 场景4:成绩判断(字符串转数值,判断等级)
const scoreInput: string = "85";
const score: number = Number(scoreInput);
const scoreLevel: string = score >= 90 ? "优秀" : (score >= 80 ? "良好" : (score >= 60 ? "及格" : "不及格"));
console.log(`【场景4】输入成绩:${scoreInput} → 转换后:${score} → 等级:${scoreLevel}`); // 良好
// 场景5:空值处理(用户昵称未设置时显示默认值)
const nickname: string | null = null;
const showName: string = (nickname ?? "游客").trim() || "游客";
console.log(`【场景5】用户昵称:${nickname} → 显示:${showName}`); // 游客
// 场景6:鸿蒙UI文本适配(去除首尾空格+空值显示默认文案)
const userInput: string | undefined = " "; // 用户输入仅空格
const showText: string = (userInput ?? "").trim() || "请输入内容";
console.log(`【场景6】用户输入:${userInput} → UI显示:${showText}`); // 请输入内容
}
运行效果
========== 实战练习 ==========
【场景1】商品价格:2999 → 格式化后:2999.00元
【场景2】手机号:13812345678 → 隐藏后:138****5678
【场景3】输入年龄:24a → 转换后:24 → 是否成年:true
【场景4】输入成绩:85 → 转换后:85 → 等级:良好
【场景5】用户昵称:null → 显示:游客
【场景6】用户输入: → UI显示:请输入内容
八、完整页面调用代码(Index.ets)
// src/main/ets/pages/Index.ets
import {
testPrimitiveAndWrapper,
testNumberWrapperMethods,
testStringWrapperMethods,
testBooleanWrapperMethods,
testNumberStringConversion,
testBooleanConversion,
testNullUndefinedSafeConversion,
testPracticalScenario
} from '../utils/WrapperTypeConvertTest';
@Entry
@Component
struct Index {
aboutToAppear(): void {
// 按顺序调用所有学习函数
testPrimitiveAndWrapper();
testNumberWrapperMethods();
testStringWrapperMethods();
testBooleanWrapperMethods();
testNumberStringConversion();
testBooleanConversion();
testNullUndefinedSafeConversion();
testPracticalScenario();
}
build() {
Column() {
Text("ArkTS内置对象与类型转换")
.fontSize(30)
.fontWeight(FontWeight.Bold)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center);
}
}
九、核心开发规范与注意事项
-
内置对象使用规范:
- 优先使用原始值,禁止手动创建
new Number()/new String()等内置对象; - 字符串截取优先用
slice()(支持负数索引),避免substring(); - ArkTS内置对象与原始值运算前,需显式调用
valueOf()拆箱; toFixed返回字符串类型,若需数值运算必须先通过Number()转为数值。
- 优先使用原始值,禁止手动创建
-
类型转换规范:
- 所有转换必须显式进行,禁止
num + ""、+str等隐式写法,否则会变成字符串拼接。 - 字符串转数值:严格验证用
Number(str),宽松处理用parseInt()/parseFloat(); - 布尔值转换优先用
Boolean(value)或!!value,遵循强类型规则。
- 所有转换必须显式进行,禁止
-
空值处理规范:
- 处理
null/undefined时必须先判断,结合??设置默认值(如null ?? ""); - 数值型默认值(年龄、库存、价格)优先用
??,避免||误判0为无效值; - 避免直接转换空值,防止出现"null"、NaN等无效结果。
- 处理
十、内容总结
- 核心规则:ArkTS内置对象(
Number/String/Boolean)需显式调用valueOf()获取原始值后,才能与对应原始值运算; - 高频方法:
Number:toFixed(数值格式化)、parseInt/parseFloat(字符串转数值)、Number.isNaN(NaN判断);String:slice(截取)、includes(包含判断)、trim(去空格)、replace(替换);Boolean:Boolean()/!!(类型转换)。
- 类型转换:强类型下必须显式转换,数值↔字符串用
toString()/Number(),布尔值转换用Boolean()/!!; - 边界处理:
null/undefined需先判断再转换,优先用??(空值合并)而非||(逻辑或)。
十一、代码仓库
- 工程名称:WrapperTypeConvertDemo
- 仓库地址:https://gitee.com/juhetianxia321/harmony-os-code-base.git
十一、下节预告
下一节将学习复杂数据类型入门——数组、元组,重点包括:
- 掌握数组的声明、初始化、访问与高频内置方法(增删改查、筛选、排序);
- 理解元组的核心特性(固定长度、固定类型),区分元组与数组的差异;
- 结合业务场景使用数组存储同类型数据、元组存储不同类型关联数据。
浙公网安备 33010602011771号