void 0,到底在保护什么?

在早期 JavaScript 环境中,undefined 并非一个不可变的“原始值”。开发者可以在全局作用域中对其重新赋值,从而导致对“未定义”状态的不确定判断。

为了解决这一历史遗留问题,社区中出现了使用 void 运算符稳定 地获取原生的 undefined 值的做法,典型写法是 void 0

历史背景与问题起因

1、undefined 不是关键字,也不是保留字

undefined 是 全局对象 window 的一个只读属性(历史问题)。

全局环境

局部环境

const m = () => {
  var undefined = 10;
  console.log(undefined); // 10
};
m();

因此当一个函数返回 undefined 时,会有隐患。

2、导致“防御式编程”负担

为了避免全局 undefined 被污染,开发者通常要先做:

var undef;        // 本地变量 undef 默认为 undefined
if (foo === undef) { /* … */ }

使得代码冗长且不直观。

因此,一个可靠且不可被重写的方式来获取原生 undefined 值,变得尤为重要。 

void 运算符简介

1、语法

void <expression>

 对 <expression> 进行求值(可以产生副作用),但始终返回 原始的 undefined

void 0      // 返回 undefined
void (1+2)  // 执行 1+2,但丢弃结果,返回 undefined

2、优先级与使用注意

void 的优先级较低,通常需要使用小括号来明确: 

void 2 === 2      // 相当于 (void 2) === 2,返回 false
void (2 === 2)    // 返回 undefined

3、为什么是 void 0?void 1、void 3 可以吗?

  • void 对操作数的值毫不关心:无论是 void 0、void 1、void (Math.random()),最终结果都相同:undefined。
  • 之所以常用 0,主要因为:简洁:单字符文字减少键入量与视觉干扰。无副作用:0 为纯数值常量,无函数调用、属性读取等开销及异常风险。

因此,技术上以 void 1、void 3 或其它表达式替代 void 0 都合法,但并不常见。

void 0 vs undefined

项目undefinedvoid 0
可写性非严格模式下可被覆盖永远不可覆盖
代码可读性直观、语义明确需理解 void 语义
字节数消耗9 个字符6 个字符(void 0)
执行开销与普通变量访问一致多一个操作符,开销微乎其微

注意一点:

在 JavaScript 中,undefined 是一个原始值(primitive),表示一个变量已经声明但尚未赋值。

let a;
console.log(a); // undefined

除此之外,undefined 在 ECMAScript 规范中是:

  • 一个全局变量(但不是保留字)
  • 可以被重新赋值或重新声明(在某些情况下)
  • 它的值是 undefined(本身就是字面量)

为什么输出不一样呢?

const undefined = 1;
console.log(undefined); // 1

let undefined = 1;
console.log(undefined); // 1

var undefined = 1;
console.log(undefined); // 1

undefined = 1;
console.log(undefined); // undefined

1、const、let

这里的 undefined 是自定义的一个块级常量变量。它遮蔽了全局的 undefined。所以 console.log(undefined) 打印的是声明的常量值 1。

2、var

用 var 声明的变量会被提升到函数作用域或全局作用域中。仍然会覆盖全局对象上的 undefined。所以它变成了赋值的 1。注意:这也意味着污染了全局变量。

3、undefined = 1

  • 在 严格模式下,这段代码会报错,因为 undefined 是只读的。
  • 在 非严格模式下(默认),可以写 undefined = 1,但实际上赋值不会生效!
(function () {
  undefined = 1;
  console.log(undefined); // undefined
})();

为什么呢?

  • undefined 虽然不是保留字,但在某些环境中,JavaScript 不会真的改变它的值,或者试图改的时候根本没有效果。
  • 从 ECMAScript 5 开始,全局变量 undefined 是不可写的(non-writable),即使试图赋值,它仍然是 undefined。
附加补充

1、在 URL 和 JSX 中的应用

在 HTML <a> 标签的 href 中:

<a href="javascript:void(0)">点击无跳转</a>

可以防止页面因 href="javascript:..." 返回非 undefined 值而跳转新内容。 

在 React/JSX 中避免页面刷新:

<a href="#" onClick={e => { e.preventDefault(); /* ... */ }}>
  链接
</a>
// 或
<a href="javascript:void(0)">链接</a>

2、与 IIFE(立即调用函数表达式)的结合

早期:为了在不将函数定义解析为声明的前提下,直接执行匿名函数。

void function(){
  console.log('IIFE');
}();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值