大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发,您的支持是我不断创作的动力。
什么是 void 运算符
void 运算符允许在需要表达式结果为 undefined 的地方对产生值的表达式进行求值。
const output = void 1;console.log(output);// 输出: undefinedvoid console.log("expression evaluated");// 输出: "expression evaluated"void (function iife() { console.log("iife is executed");})();// 输出: "iife is executed"void function test() { console.log("test function executed");};try { test();} catch (e) { console.log("test function is not defined"); // 输出: "test function is not defined"}void 运算符通常只用于获取 undefined 原始值,一般使用 void(0) 或 void 0,当然也可以使用全局变量 undefined。
但是需要注意 void 运算符的优先级,例如:
void 2 === "2";// (void 2) === '2', 返回 falsevoid (2 === "2");// void (2 === '2'), 返回 undefinedvoid 用于立即执行函数表达式
使用立即执行函数表达式 (Immediately-invoked Function expression) 时,function 关键字不能位于语句的开头,因为会被解析为函数声明,从而在到达表示调用的括号时会产生语法错误。
例如,下面是标准的 IIFE 表达式:
// standard IIFE(function () { // statements…})();// arrow function variant(() => { // statements…})();// async IIFE(async () => { // statements…})();而下面的 IIFE 是非法的:
function iife() { console.log("Executed!");}();// 报错 SyntaxError: Unexpected token ')'function () { console.log("Executed!");}();// 报错 SyntaxError: Function statements require a function name因此,为了使函数能够被解析为表达式,function 关键字必须出现在仅接受表达式 (expressions) 而非语句 (statements) 的位置。
开发者可以在关键字前添加一个一元运算符 (Unary Operator) 来实现,该运算符仅接受表达式作为操作数。而函数调用的优先级高于一元运算符,因此其会被优先执行,返回值 undefined 会被传递给一元运算符然后被丢弃。
在所有一元运算符中,void 提供了最佳的语义,其清楚地表明函数调用的返回值应该被丢弃。
void (function () { console.log("Executed!");})();// 输出 "Executed!"虽然比用括号括起来的函数表达式要长一些,但与强制将 function 关键字解析为表达式的开头而不是语句的开头具有相同的效果。
(function () { console.log("Executed!");})();需要注意的是,此技巧仅适用于使用 function 关键字定义的 IIFE。
而使用 void 运算符来避免箭头函数的括号则会产生语法错误,箭头函数表达式在调用时始终需要使用括号。
void () => { console.log("iife!"); }();// 报错 SyntaxError: Malformed arrow function parameter listvoid 运算符用于 Javascript URI
Javascript URL(以 javascript: 为前缀的 URL)被用作虚假的导航目标,在浏览器尝试导航时会执行 Javascript 代码。如果 URL 的值为字符串,则会将其视为 HTML 并由浏览器渲染。
例如下面示例中,<a> 元素的 href 属性设置为 javascript: URL,该 URL 导航到包含内容 “Hello, world!” 的新页面:
<a href="javascript:pageContent">Click me</a><script> // Use a var so it becomes a global variable and can be read elsewhere var pageContent = "Hello, world!";</script>当然,开发者可以通过 void(0) 明确返回 undefined 以避免页面跳转。
<a href="javascript:void(0);">Click here to do nothing</a>// 点击无效果<a href="javascript:void(document.body.style.backgroundColor='green');"> Click here for green background</a>// 点击时将页面背景色设置为 green,如果不用 void 包裹代码还会跳转到// 一个只有 `green` 字符串的新页面但是需要注意的是,由于 javascript: URL 不会创建历史记录,因此无法在不刷新的情况下返回上一页。
无泄漏箭头函数 (Non-leaking Arrow Functions)
箭头函数引入了一种返回表达式的简写无括号语法,而如果表达式是函数调用,并且返回值为非 undefined 则可能会导致意外的副作用。
例如,如果下面代码 doSomething() 返回 false,则 checkbox 在被点击时将不再被标记为选中或未选中,因为从处理程序返回 false 会禁用默认操作。
checkbox.onclick = () => doSomething();而这可能不太符合预期!为了安全起见,当函数的返回值不打算使用时,可以将其传递给 void 运算符,以确保 API 更改不会导致箭头函数的行为发生变化。
checkbox.onclick = () => void doSomething();参考资料
https://developer.mozilla.org/en-US/docs/Web/Javascript/Reference/Operators/void
https://stackoverflow.com/questions/1291942/what-does-javascriptvoid0-mean
https://developer.mozilla.org/en-US/docs/Glossary/IIFE
https://developer.mozilla.org/en-US/docs/Web/URI/Reference/Schemes/javascript
https://sabe.io/blog/javascript-void0
