js和ts中的null与undefined

本文详细解释了JavaScript中null和undefined的区别,特别是在Midway框架和数据库操作中的应用。介绍了如何在TypeScript中安全地处理这些空值,包括使用NullishCoalescing运算符和可选链操作符来提升代码的鲁棒性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文在个站同步发布,您可以在>>这里看到最新的文章。

1 定义

特别说明,本文中的undefinednull指变量的字面值:

  • undefined:已声明但未初始化的变量值
  • null:未定义(不存在)的变量值

例如:

var var1: number;
var var2: number = null;

在以上代码中,var1的值为undefined,而var2则被显式地定义为null

不过需要注意的一点是,使用typeof查看上述变量var2的类型时,返回值并不是null

console.log(typeof undefined); //'undefined'
console.log(typeof var1); //'undefined'

console.log(typeof null); //'object'
console.log(typeof var2); //'object'

2 null/undefined变量

2.1 常见场景举例

1、变量值为undefined

Midway框架中,通常在Controller中通过装饰器写法声明需要接收的参数,例如:

// src/controller/user.ts
// POST /user/ HTTP/1.1
// Host: localhost:3000
// Content-Type: application/json; charset=UTF-8
//
// {"uid": "1", "name": "harry"}
import { Controller, Post, Body } from '@midwayjs/core';

@Controller('/user')
export class UserController {
  @Post('/')
  async updateUser(@Body('uid') uid: string): Promise<User> {
    // id 等价于 ctx.request.body.uid
  }
}

※以上代码摘自Midway (midwayjs.org)

此时,若客户端未在请求中传送需要的参数uid,则uid = undefined,因为uid已被声明但尚未初始化。

2、变量值为null

进行数据库操作时,如果数据库中某个非必填字段的值为null,那么相应的,Prisma ORM返回的字段属性值也为null

// ...前略
export class UserService {
	@Inject
	db:DB //注入

	async updateUser(uid: string, data:User){
		const res = await this.db.user.update({
          where: { uid },
          data,
        });
	}
}

update API的返回值为User类型的JavaScript对象,假设表中的age为非必填字段,且没有设置合适的初始值,那么上述代码中的res.age就有可能为null

2.2 初始化

为保证代码的鲁棒性,理应在业务代码前先对可能出现undefinednull(下文统称为“空值”)的入参进行处理。

在JavaScript中常见的做法是使用||运算符处理空值,例如:

uid = uid || '';

这段代码的出发点是,当uid为空值时,执行uid = ''。但由于||运算符不仅会放行空值,还会放行0、false,因此当参数为数值型或布尔型时,需要使用typeof结合三元运算符进行处理。

TypeScript语言考虑到上述情况,新增了一种名为Nullish Coalescing的运算符,也就是我们常说的双问号运算(??)。这种运算支持识别nullundefined,在处理空值时不再需要对数值型和布尔型数据进行特判:

null ?? "Value";
// "Value"

undefined ?? "Value";
// "Value"

false ?? true;
// false

0 ?? 100;
// 0

"" ?? "n/a";
// ""

NaN ?? 0;
// NaN

※上述代码摘自这篇博文

因此,我们可以这样对入参进行处理

uid = uid ?? '';

3 判别

1、判别是否为nullundefined

var x;
if(x==null){
	console.log(`x is null or undefined`);
}

2、判断是否为null

if(x===null){
	console.log(`x is null`);
}

注意,【不可以】使用typeof进行判断,如果你忘了为什么,可以复习一下第1节的最后一个code block。

3、判断是否为undefined

if(typeof x === 'undefined'){
	console.log(`x is undefined`);
}

4 鲁棒性写法

为防止对象或对象的某一个属性对象为空,导致代码报错,TypeScript提出了一种叫做“可选链?.”的运算符,它的功能是:在访问对象属性的过程中遇到空值时,①立即停下,②返回undefined。例如:

const obj =
{
    branch1: {
    }
}

console.log(obj.branch1?.emp1?.name); //undefined

※以上代码摘自这篇博文

由于obj.branch.emp1未定义,返回undefined

使用可选链运算符,就可以省去逐层判空的代码了。

【写在最后】

在ts中,nullundefined也是数据类型。默认情况下,nullundefined是所有类型的子类型,正因为如此,它们才能作为字面值赋给其它类型的变量。

参考

文章参考的博文:

文章中提到的框架:

### TypeScript 中 `null`、`NaN` `undefined` 的区别及使用场景 #### 定义特性 在 TypeScript 中,`null`、`NaN` `undefined` 是三种不同的基础类型,它们各自有不同的定义用途。 - **`null`**: 这是一个显式的空值,表示有意设置为空的对象或变量。它通常用于初始化那些尚未赋实际值的变量或者作为某些操作的结果来表明不存在有效数据的情况[^1]。 - **`undefined`**: 当声明了一个变量但未对其赋予任何初始值时,默认情况下该变量会被分配为 `undefined` 类型。此外,如果访问对象中不存在的属性也会得到 `undefined` 值。 - **`NaN` (Not-a-Number)**: 虽然名字里带有 “数”,但实际上它是用来标志错误计算结果的一个特殊数值——即当尝试执行无法得出合理数字的操作(比如除以零或其他非法运算)时产生的标记。值得注意的是,尽管它的名称暗示其属于数字类别,但在 JavaScript/TypeScript 的语境下,`typeof NaN === 'number'` 返回 true[^2]。 #### 使用场景分析 对于这三者来说: - 如果你需要表达某个东西确实存在只是当前状态为空,则应该选用 `null`;例如数据库查询可能返回一条记录也可能不返回,在这种情形下可以考虑用 `null` 来代表无匹配项的情形。 - 对于还未被设定具体值得新创建出来的变量或者是函数参数列表里的可选参数而言,更倾向于采用默认值形式呈现出来就是 `undefined` ,因为这样能够清晰反映出这些位置还没有接收到有效的输入信息。 - 至于 `NaN`, 主要应用于数学处理过程中遇到异常状况的时候, 如非数值字符串转换成整数失败等情况. 以下是几个简单的例子展示如何正确运用他们: ```typescript // Example of using null let user: string | null = null; if(user){ console.log(`User name is ${user}`); }else{ console.log('No user provided'); } // Example of using undefined function greet(name?:string):void { if(!name){ console.log('Hello stranger!'); }else{ console.log(`Hello ${name}!`); } } greet(); // Output: Hello stranger! // Example involving NaN const result:number = parseFloat("abc"); console.log(result); // Outputs: NaN ``` 以上代码片段分别演示了何时以及怎样去利用 `null`,`undefined` 及 `NaN`. ### 结论 综上所述,理解并区分好这三个概念有助于编写更加精确可靠的程序逻辑结构。记住每种类型的独特含义及其适用场合可以帮助开发者避免潜在陷阱从而提升软件质量。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值