一文彻底搞懂javascript中的undefined

undefined in javascript

undefined是可以说是javascript中最特殊的一个类型,许多其他语言中都没有这个类型。它表示一个变量已经声明,但还没有被赋值。

js 复制代码
let a; // a的值是undefined

如果没有掌握好undefined,则可能会写出一些非常业余的代码,我们来看一个例子,这是在做code review时遇到的真实例子,你能看出下面的代码有什么问题吗?

js 复制代码
function getUserName(user) {
  if (user) {
    return user.name;
  } else {
    return undefined;
  }
}

在揭晓答案之前,我们先系统学习一下什么情况下JavaScript会产生undefined类型。

1. 显式undefined类型

jsx 复制代码
const a = undefined;
console.log(a); // undefined.

2. 未初始化的变量

jsx 复制代码
let a;
console.log(a); // undefined.

3. 访问对象中不存在的属性

jsx 复制代码
const person = {
  name: 'zdd',
  age: 41,
};

console.log(person.gender); // undefined.


const a = [1, 2, 3];
console.log(a[3]); // 数组只有三个元素,而a[3]表示第四个元素,所以它们的值是undefined

4. 函数没有返回值

函数没有返回值的时候,实际上返回的就是undefined

jsx 复制代码
function test() {
  console.log('hello, world!');
}

console.log(test()); // undefined.

5. 调用函数没有传递对应的参数

下面的代码中,函数add没有传入任何参数,所以ab的值都是undefined

jsx 复制代码
function add(a, b) {
  console.log(a); // 输出undefined.
  console.log(b); // 输出undefined.
  return a + b;
}

add(); // 没有传递参数

undefined != not defined

需要注意的是,undefinednot defined是两个不同的概念。undefined表示一个变量已经声明但还没有被赋值,而not defined表示一个变量没有被声明。

jsx 复制代码
let a;
console.log(a); // undefined.
console.log(b); // error, b is not defined

undefined vs void 0

既然已经有了undefined,为什么有很多JavaScript库中还使用void 0呢? 原因就是undefined是一个值,而不是关键字,能被用户串改,看下面的代码:

jsx 复制代码
const undefined = 1; // undefined被用户篡改!

const add = (a, b) => {
  // 这里判断参数是否传入,结果失效了,因为undefined值在前面被改成了1
  if (a === undefined || b === undefined) {
    console.error('请输入两个数');
  } else {
    return a + b;
  }
};

add(1, 2); // 这里会执行add函数中的if分支,是不是很崩溃?

使用void 0就不会有这个问题。

jsx 复制代码
const undefined = 1;

const add = (a, b) => {
  // 写成void 0就没有问题了,无论undefined被改成什么,都不影响。
  if (a === void 0 || b === void 0) {
    console.error('请输入两个数');
  } else {
    return a + b;
  }
};

console.log(add(1, 2));

那么为什么void 0返回undefined呢?这是因为void是一个操作符,它的作用是对其后面的表达式求值,然后返回undefined。在JavaScript中,void 0等价于undefined,其实你也可以写void 1, void 'hello'等,结果都是undefined

void expression的求值规则 - 先对expression求值,然后返回undefined

正则表达式中的undefined

在正则表达式中,可以使用test来测试某个字符串是否满足特定的规则。

javascript 复制代码
console.log(/^hello/.test('hello, world!')); //true

如果你没有传递参数给test,那么它会尝试匹配字符串undefined.

javascript 复制代码
console.log(/undefined/.test()); // true

This is equivalent to the following code, since undefined convert to string is 'undefined', so the result is true.

javascript 复制代码
console.log(/undefined/.test(undefined));

详情请看这里

undefined vs null

undefinednull经常被放到一起比较,那么他们之间有什么区别呢?

  • undefined表示一个变量已经声明但还没有被赋值,
  • null表示一个变量已经被赋值为一个空值。
  • null是JS中的关键字,但是undefined是一个全局属性。

undefined与其他类型之间的转换

这里面比较特殊的是和数字类型之间的转换,undefined转换为数字类型时会返回NaN,而null转换为数字时会返回0

javascript 复制代码
console.log(String(undefined)); // "undefined"
console.log(Number(undefined)); // NaN
console.log(Boolean(undefined)); // false

注意null转换为其他类型时与undefined的区别

javascript 复制代码
console.log(String(null)); // "null"
console.log(Number(null)); // 0
console.log(Boolean(null)); // false

回到文章开始的问题,根据上面第四点,函数没有返回值时,返回的就是undefined,所以上面的代码可以简化为如下形式,else分支完全没有必要。

js 复制代码
function getUserName(user) {
  if (user) {
    return user.name;
  }
}

References:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#undefined_type
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void

相关推荐
无羡仙19 分钟前
替代 Object.freeze 的精准只读模式
前端·javascript
小菜全1 小时前
uniapp新增页面及跳转配置方法
开发语言·前端·javascript·vue.js·前端框架
白水清风1 小时前
关于Js和Ts中类(class)的知识
前端·javascript·面试
前端Hardy1 小时前
只用2行CSS实现响应式布局,比媒体查询更优雅的布局方案
javascript·css·html
车口2 小时前
滚动加载更多内容的通用解决方案
javascript
艾小码2 小时前
手把手教你实现一个EventEmitter,彻底告别复杂事件管理!
前端·javascript·node.js
Jedi Hongbin5 小时前
Three.js shader内置矩阵注入
前端·javascript·three.js
掘金安东尼5 小时前
Node.js 如何在 2025 年挤压 I/O 性能
前端·javascript·github
得物技术6 小时前
前端日志回捞系统的性能优化实践|得物技术
前端·javascript·性能优化
ZKshun6 小时前
[ 前端JavaScript的事件流机制 ] - 事件捕获、冒泡及委托原理
javascript