欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

JavaScript 基础:无效 0 的魔力

最编程 2024-04-20 19:23:52
...

这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战

众所周知,Undefined是JS语言中的7大基本类型之一,表示未定义,它的值只有一个,就是undefined。任何变量在赋值前都是undefined。

而在一些框架源码中,会出现一些这样的表达式:

function foo() {
    var a  = arguments[0] !== (void 0 ) ? arguments[0] : 2;
    return a; 
}

这是 《你不知道的JavaScript》的一段代码,用于实现 ES6 中函数参数默认值的 transpiling 处理,为了让不支持 ES6 这个新特性的浏览器可以正常使用。

正如你可以看到的,它会检查arguments[0]的值是否为void 0(也就是undefined),如果是的话就提供默认值2;否则就使用传入值。

1.为什么用 void 0 代替 undefined?

void 0 返回undefined,我们都知道的,但是为什么不直接 arguments[0] !== undefined?

我们先来解释一下什么是void?

MDN中对void有这么一段说明:

The void operator evaluates the given expression and then returns undefined.

翻译过来意思是:void操作符对给定的表达式求值,然后返回undefined。

在 JavaScript 中 void 是一元运算符,出现在操作数的左边,操作数可以是任意类型的值,void右边的表达式可以是带括号形式(例如:void(0)),也可以是不带括号的形式(例如:void 0)。

1.undefined可以被重写

在ES5的全局环境中,undefined是只读的。而在局部作用域中,undefined是可变的。这个是JS语言公认的设计失误之一。

比如:

(function() {
  var undefined = 10;
 
  // 10 -- chrome
  alert(undefined);
})();
 
(function() {
  undefined = 10;
 
  // undefined -- chrome
  alert(undefined);
})();

2.从性能方面: void 0 比 undefined 少了三个字节

当源码中有大量用 undefined 判断的时候,这个优化还是值得关注的。

>"undefined".length
9
>"void 0".length
6

3. 保证结果不变性

undefined并不是javascript中的保留字,我们可以使用undefined作为变量名字,然后给它赋值。void 0输出唯一的结果undefined,保证了不变性。

2.void 0 应用场景

(1)立即调用的函数表达式

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

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

    foo();
    biz();
}();

(2)javascript URIs

当用户点击一个以 javascript: 开头的URI 时,它会执行URI中的代码,然后用返回的值替换页面内容,除非返回的值是undefinedvoid运算符可用于返回undefined。例如:

<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 代码是不推荐的,推荐的做法是为链接元素绑定事件。

(3)箭头函数中避免泄漏

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

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