JavaScript void 运算符

简介: 前两天在开发项目的公共基础库时,无意间在看 moment.js 源代码的时候发现这样一个 util 函数。这个函数作用无非就是判断输入否是 undefined ,这个不是关键,关键是 void 这个引起了我的注意,这里为什么不直接使用 input === undefined ?而是使用这种形式来判断了。带着疑问我们今天就一起来看看 JavaScript void 运算符。

网络异常,图片无法展示
|


目录


  1. void 是什么?
  2. void 的作用
  3. void 优先级
  4. void 的执行
  5. 为什么要用 void ?


前言


前两天在开发项目的公共基础库时,无意间在看 moment.js 源代码的时候发现这样一个 util 函数。这个函数作用无非就是判断输入否是 undefined ,这个不是关键,关键是 void 这个引起了我的注意,这里为什么不直接使用 input === undefined ?而是使用这种形式来判断了。带着疑问我们今天就一起来看看 JavaScript void 运算符。


export default function isUndefined(input) {
    return input === void 0;
}


1. void 是什么?


void 运算符 对给定的表达式进行求值,然后返回 undefined。语法就是 void expression 。void 是一个一元运算符,它可以出现在任意类型的操作数之前执行操作数,却忽略操作数的返回值,返回一个 undefined。void 在表达式的左边,void 右边的表达式可以是带括号形式(例如:void(0)),也可以是不带括号的形式(例如:void 0)。


2. void 的作用


1. JavaScript URIs


如果有印象的同学是不是会发现,我们在阻止 a 标签的默认事件是会用到这个。


<a href="javascript:void(0);">
<a href="javascript:void(0);">
  这个链接点击之后不会做任何事情,如果去掉 void(),
  点击之后整个页面会被替换成一个字符 0。
</a>
<p> 
  chrome中即使<a href="javascript:0;">也没变化,firefox中会变成一个字符串0 
</p>
<a href="javascript:void(document.body.style.backgroundColor='green');">
  点击这个链接会让页面背景变成绿色。
</a>


注意,虽然这么做是可行的,但利用 javascript: 伪协议来执行 JavaScript 代码是不推荐的,推荐的做法是为链接元素绑定事件。


2. 立即调用的函数表达式


在使用立即执行的函数表达式时,可以利用 void 运算符让 JavaScript 引擎把一个function关键字识别成函数表达式而不是函数声明(语句)。


void function iife() {
    var bar = function () {};
    var baz = function () {};
    var foo = function () {
        bar();
        baz();
     };
    var biz = function () {};
    foo();
    biz();
}();


3. 在箭头函数中避免泄漏


箭头函数标准中,允许在函数体不使用括号来直接返回值。 如果右侧调用了一个原本没有返回值的函数,其返回值改变后,则会导致非预期的副作用。 安全起见,当函数返回值是一个不会被使用到的时候,应该使用 void 运算符,来确保返回 undefined(如下方示例),这样,当 API 改变时,并不会影响箭头函数的行为。


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


确保了当 doSomething 的返回值从 undefined 变为 true 的时候,不会改变函数的行为。


3. void 优先级


由于 void 运算符的优先级比较高(14),高于普通运算符的优先级,所以在使用时应该使用小括号明确 void 运算符操作的操作数,避免引发错误。 在下面的示例代码中,由于第一行没有使用小括号,void 运算符优先计算,恒等于( void 2)- 1,也就是 undefined - 1,结果为 NaN,在第二行代码中用括号包含了 (2-1),所以优先于是先计算2-1,在处理 void,恒等于 void (1),结果也就是 undefined。


console.log(void 2 - 1);  //返回NaN
console.log(void (2 - 1));  //返回undefined


4. void 的执行


网络异常,图片无法展示
|


在 262 ECMA 中,对 void 有一个执行步骤的解释,大致的解读一下:


  1. 执行 UnaryExpression 并把返回值赋值给 expr
  2. 调用 GetValue(expr)
  3. 返回 undefined


注意最后的一句话,GetValue一定要调用,即使它的值不会被用到,但是这个表达式可能有副作用。其实这个副作用是什么,并没有解释。既然void xx === undefined,我们回到最开始的问题,哪 void 0 、void 100、void xx()、void 不管什么操作,返回的都是 undefined 。哪为什么在 moment.js 中不直接写 input === undefined。


5. 为什么要用 void ?


我们知道 undefined 在 JavaScript 中是一个保留字。哪既然他是一个保留字,我们就可以为它赋值。


function test() {
    var undefined = "不爱吃猫的鱼er";
    console.log(undefined); // 不爱吃猫的鱼er
}
test();
console.log(undefined); // undefined

网络异常,图片无法展示
|
赋值之后


你提取到的 undefined 就不等于 undefined了,当然如果我们使用的是 window 对象上的 undefined,也可能被赋值 。所以你直接使用的 undefined ,不一定是100%可靠。于是在很多框架或者基础 JS 库中,采用void方式获取 undefined 便成了通用准则。例如 moment.js、Backbone.js、underscore.js,在他们的源码中对 undefined 的使用都是使用 void 0 代替。 • moment.js


export default function isUndefined(input) {
    return input === void 0;
}

• Backbone.js

if (callback !== void 0 && 'context' in opts && opts.context === void 0) opts.context = callback;

• underscore.js

_.isUndefined = function(obj) {
    return obj === void 0;
}


除了采用void能保证取到 undefined 值以外,AngularJS 的源码里通过函数调用不传参数,确保了 undefined 参数的值是一个 undefined。


(function(window, document, undefined) {
    //.....
})(window, document);


总结


通过 void xx 这种方式来获取 undefined,比直接使用 undefined 来的更加可靠安全,所以在很多的库、框架中都使用 void xx 这种方式来处理undefined ,保证使用到的是安全可靠的 undefined。这种方式我们在日常的项目开发或者的封装也可以借鉴起来。


结束语


如果文章中什么不对或者写的不好的地方,请大家多多指正,谢谢!码字不易,点个赞加个关注吧!


参考


developer.mozilla.org/zh-CN/docs/…262.ecma-international.org/5.1/#sec-11…segmentfault.com/a/119000000…blog.csdn.net/mm19931027/…

目录
相关文章
|
5月前
|
前端开发 JavaScript 安全
javascript:void(0);用法及常见问题解析
【6月更文挑战第3天】JavaScript 中的 `javascript:void(0)` 用于创建空操作或防止页面跳转。它常见于事件处理程序和超链接的 `href` 属性。然而,现代 web 开发推荐使用 `event.preventDefault()` 替代。使用 `javascript:void(0)` 可能涉及语法错误、微小的性能影响和XSS风险。考虑使用更安全的替代方案,如返回 false 或箭头函数。最佳实践是保持代码清晰、安全和高性能。
270 0
|
1月前
|
JavaScript
js运算符
js运算符
19 5
|
26天前
|
JavaScript 前端开发
JavaScript 运算符全知道
JavaScript 运算符全知道
49 0
|
2月前
|
JavaScript 前端开发
javascript:void(0) 含义
javascript:void(0) 含义
65 2
|
2月前
|
JavaScript 前端开发
JavaScript 运算符
JavaScript 运算符
19 3
|
3月前
|
JavaScript 前端开发
JavaScript 中的 typeof 运算符
【8月更文挑战第29天】
23 1
|
3月前
|
JavaScript 前端开发 安全
深入理解JavaScript中的比较运算符
深入理解JavaScript中的比较运算符
|
3月前
|
前端开发 JavaScript 程序员
聊聊前端 JavaScript 的扩展运算符 “...“ 的使用场景
聊聊前端 JavaScript 的扩展运算符 “...“ 的使用场景
|
3月前
|
JavaScript 前端开发
JS常见的运算符有哪些?
JS常见的运算符有哪些?
|
3月前
|
JavaScript 前端开发
JavaScript基础&实战(2)js中的强制类型转换、运算符、关系运算符、逻辑运算符、条件运算符
这篇文章详细介绍了JavaScript中的强制类型转换、运算符(包括算术、逻辑、条件、赋值和关系运算符)的使用方法和优先级规则。
JavaScript基础&实战(2)js中的强制类型转换、运算符、关系运算符、逻辑运算符、条件运算符