Skip to content

Latest commit

 

History

History
119 lines (79 loc) · 4.1 KB

undefined 和 void 的区别.md

File metadata and controls

119 lines (79 loc) · 4.1 KB

undefined 和 void 的区别

void 是一个运算符,它对给定表达式求值,然后返回 undefined

区别

在支持 ES5 的现代浏览器中,直接使用 void 运算符和 undefined 的值没有区别:

void 0 === undefined // true
void 1 === undefined // true
void 'Foo' === undefined // true

但是,在运行 ES3 引擎的旧浏览器中,undefined 是一个全局属性,可以更改。

// 在 ES3 中
console.log(undefined)
var undefined = 'foo'
console.log(undefined) // 'foo'

另一方面,void 运算符不能被重写。因此,void 被用作 undefined 值的替换,以安全的方式获取 undefined 值。

你可以在一些 JS 项目中看到这种情况,它们更喜欢用 void 而不是 undefined,以避免意外创建名为 undefined 的变量。由于这个原因,甚至有一个 ESLint 规则不允许 undefined

但在 ES5 中,undefined 有了新的修订,它不能在被重写,因为它被 Writeable 设置为 false

扩展

  • void 是一个运算符,而不是一个函数。因此,我们不需要将表达式括在括号中。void 0 相当于 void(0)
  • 有些压缩器使用 void 0 来缩短 undefined 的长度。
  • 如果使用立即调用的函数表达式(称为 IIFE),则可以使用 voidfunction 关键字视为表达式,而不是声明。

以下是一个 IIFE 函数:

;(function run() {
  console.log('Executed')
})()

我们可以使用 void 运算符作为括号的替代。因为 void 是一个一元运算符,所以它告诉 JavaScript 将函数声明视为一个表达式。

void (function run() {
  console.log('Executed')
})()

不同之处在于,正常的 IIFE 仍然可以返回一个值,而对 IIFE 使用 void 将始终求值为 undefined

  • 当与箭头函数一起使用时,可以使用 void 来避免副作用。

正如我们所知,ES6 箭头函数允许通过省略函数体中的大括号来使用函数的返回值。

const sum = (a, b) => a + b

在某些情况下,我们不打算使用函数的返回值,因为它可能导致不同的行为。假设我们要处理一个按钮的点击事件:

button.onclick = () => doSomething()

它照常工作,直到有人更改 doSomething,并使其返回 boolean。在返回 false 的情况下,将跳过 click 事件的默认行为,这可能是你不希望看到的。

将结果传递给 void 将确保无论执行函数的结果如何,它都不会改变箭头函数的行为:

button.onclick = () => void doSomething()

在 React、Svelte 等现代库中可以看到使用 void 和箭头函数的优势。

这些库允许我们在将组件装入 DOM 之后立即执行函数。例如,React 提供 useEffect,Svelte 具有 onMount

如果我们在回调函数中返回一个函数,那么该函数将被调用以清理内容,在组件从屏幕上移除之前释放内存。

// React 示例代码
useEffect(() => doSomething())

它可以在运行时产生 bug。为了避免这种情况,我们可以使用 void

useEffect(() => void doSomething())

或使用大括号:

useEffect(() => {
  doSomething()
})

建议

在以 javascript: 为前缀的 URL 中使用了 void 运算符。

默认情况下,浏览器将在遵循 javascript: URI 时计算代码,然后用返回值替换页面内容。

为了防止出现默认行为,代码必须返回 undefined。这就是我们看到以下代码的原因:

<a href="javascript: void(0);" onclick="doSomething"> ... </a>

现在,不推荐使用 javascript: 协议。由于用户可以将未初始化的输入放入事件处理程序中,因此可能会产生安全问题:

<a href="javascript: alert('uninitialized input')">...</a>

从 v16.9.0 开始,React 还反对使用 javascript: URL