作为ArkTS语言的初学者,对于null与undefined的概念总会弄混,这两者有什么区别,应该如何按需的使用?相信读者们在具体的场景中使用时,都有一些疑惑。
本篇内容是《精通HarmonyOS NEXT :鸿蒙App开发入门与项目化实战》这本书第四章内容的延续,是咱这本书读者的福利,在本篇内容中通过10个示例说明在不同的场景中,null与undefined的区别与应用,每个示例可以独立的编译及调试,欢迎大家一同来深入的解这两者,甚至可以当作面试题来学习。
对本书感兴趣的同学可以点击以下链接进行购买,及参加 我的班级(华为官方)共同学习
往期福利:
示例1: 基本定义和区别
声明一个变量(或常量,以下以变量通指变量或常量)可以为undefined,当这个变量未赋值,默认为 undefined。当声明一个变量可以为null,则需要对其进行指定默认值,否则会编译报错。
// 声明一个变量可以为undefined,当这个变量未赋值,默认为 undefined。
let uninitializedVar: string | undefined;
if (uninitializedVar == undefined) { // 条件表达式为真
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', "uninitializedVar is undefined");
}
// 当声明一个变量可以为null,则需要对其进行指定默认值,否则会编译报错。
let explicitlyNull: string | null = null;
if (explicitlyNull == null) { // 条件表达式为真
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', "explicitlyNull is null");
}
// 反例,当声明一个变量可以为null,没有指定默认值。
let explicitlyNullNotInit: string | null;
if (explicitlyNullNotInit == null) { // 编译报错 Variable 'explicitlyNullNotInit' is used before being assigned
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', "explicitlyNullNotInit is null");
}
对应的log输出及编译报错的截图
- log输出
- 编译报错
示例2: 类型检查差异
undefined类型的变量的类型为undefined,null类型的变量的类型为object。
// 使用示例1中的变量uninitializedVar
const typeofUninitializedVar = typeof uninitializedVar;
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', typeofUninitializedVar); // 输出: "undefined"
// 使用示例1中的变量explicitlyNull
const typeofExplicitlyNull = typeof explicitlyNull;
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', typeofExplicitlyNull); // 输出: "object"
对应的log输出的截图
示例3: 相等性比较
undefined与null类型的宽松相等为true,严格相等为false
const nullEqqUndefined = null == undefined;
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', nullEqqUndefined ? "true" : "false"); // 输出: "true" (宽松相等)
const nullEqqqUndefined = null === undefined;
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', nullEqqqUndefined ? "true" : "false"); // 输出:" false" (严格相等)
对应的log输出的截图
示例4: 函数返回值
函数没有明确返回值时,返回 undefined,函数有明确返回为null时,需要显示的定义,且返回值可能为空
// 函数没有明确返回值时,返回 undefined
function noReturnValue(): void {
// 没有return语句
}
// 函数有明确返回为null时,需要显示的定义,且返回值可能为空
function returnNullOrStr(): string | null {
return null;
}
// 直接定义返回为空,也可以编译通过
function returnNull(): null {
return null;
}
const noReturnValueType = noReturnValue();
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', "" + noReturnValueType); // 输出: undefined
const returnNullType = returnNull();
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', "" + returnNullType); // 输出: null
对应的log输出的截图
示例5: 类对象属性访问
undefined属性在定义时可以不初始化,默认为undefined,null属性在定义时需要初始化。在创建类对象时,均需要指定初始值,否则会编译出错。
注意,可空属性在定义时可以不初始化,默认为undefined,在创建类对象时,可选指定初始值。
class Man {
name: string = ""; // 必需要初始化
age: number = 0; // 必需要初始化
address?: string | undefined; // 可以不初始化 默认值为 undefined
addressUndefined: string | undefined; // 可以不初始化 undefined
addressNull: string | null = ""; // 必需要初始化
}
// 字面量创建类对象实例
let man: Man = {
name: "俩毛豆",
age: 30,
// 没有初始化address属性,可选
addressUndefined: undefined,
addressNull: null
};
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', man.name); // 输出: "俩毛豆"
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', "" + man.address); // 输出: undefined
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', "" + man.addressUndefined); // 输出: undefined
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', "" + man.addressNull); // 输出: undefined
对应的log输出的截图
示例6: 数字转换
undefined类型转换为数字为NaN,null类型转换为数字为0,定义的变量也如此。
const numberUndefined = Number(undefined);
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', "" + numberUndefined); // 输出: NaN
// 使用示例1中的变量 uninitializedVar
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', "" + Number(uninitializedVar)); // 输出: NaN
const numberNull = Number(null);
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', "" + numberNull); // 输出: 0
// 使用示例1中的变量 explicitlyNull
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', "" + Number(explicitlyNull)); // 输出: 0
对应的log输出的截图
示例7: 布尔转换
undefined类型转换为数字为false,null类型转换为数字为false,定义的变量也如此。
注意,这点与数字转换是有不同的
const boolNull = Boolean(null);
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', "" + boolNull); // 输出: false
// 使用示例1中的变量 uninitializedVar
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', "" + Boolean(uninitializedVar)); // 输出: false
const boolUndefined = Boolean(undefined);
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', "" + boolUndefined); // 输出: false
// 使用示例1中的变量 explicitlyNull
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', "" + Boolean(explicitlyNull)); // 输出: false
对应的log输出的截图
示例8: 空值合并操作符(??)
undefined与null类型的变量,在空值合并操作符的左侧时,该操作符的值为右侧的值
function greet(name: string | null | undefined) {
// 如果name是undefined 或 null,使用默认值,常见于没有设定用户名时显示
const displayName = name ?? "Guest"; //"Guest" 仅当左侧为 null 或 undefined 时生效。
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', `Hello, ${displayName}!`);
}
greet(undefined); // 输出: Hello, Guest!
greet(null); // 输出: Hello, Guest!
greet("俩毛豆"); // 输出: Hello, 俩毛豆!
对应的log输出的截图
示例9: 数组中的表现
undefined与null类型在数组中均占位,同时也会影响数组的类型
let array = [1, null, 3, undefined, 5];
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', "" + array); // 输出: [1,,3,,5]
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', "" + array[1]); // 输出: null
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', "" + array[3]); // 输出: undefined
// 报错 Argument of type 'number[]' is not assignable to parameter of type 'string'. <ArkTSCheck>
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', array);
对应的log输出和编译报错的截图
- log输出
- 编译报错提示,注意底部的array:(number | null | undefined)
示例10: JSON序列化差异
undefined类型的属性不会被序列化、而null类型的属性会被序列化
// 类定义
interface Student {
name: string;
age: number | null;
score: number | undefined;
}
// 实例化
let student: Student = {
name: "Bob",
age: null, // 明确设置为null的属性
score: undefined // 未定义的属性
};
// 注意: undefined属性不会被序列化
hilog.info(0x008666, '俩毛豆:testNullAndUndefind', JSON.stringify(student)); // 输出: {"name":"Bob","age":null}
对应的log输出的截图
总结:
undefined与null类型在我们研发过程中经常会用到,感兴趣的同学可以基于该内容之上再进行变种的验证。
对本书感兴趣的同学可以点击以下链接进行购买,及参加 我的班级(华为官方)共同学习