二八原则:JavaScript中逗号操作符进阶用法

1,838 阅读2分钟

起因

事情的起因是这样的,最近在阅读style-loader源码时遇到这样一段代码:

code.png

难道我用的是假的JavaScript吗...

如果有大佬明白这么做的原因是为什么了...那么就可以停止阅读了。

分析

关于逗号操作符,在MDN上给出的是这样的解释:

逗号操作符  对它的每个操作数求值(从左到右),并返回最后一个操作数的值。

简单来说

let number = 1;

// 从左往右依次执行完毕后 返回最后一个值
number = (number++, number);

console.log(number);
// expected output: 2

x = (2, 3);

console.log(x);
// expected output: 3

上述代码的number = (number++, x);其实就相当于number++而已。

可能有的同学有疑问了,这样做的效果是什么呢?

单纯为了秀而秀嘛!,别着急我们接下来往下看另外一个例子:

window.name = 'wang.haoyu'

const obj = {
  name:'19Qingfeng',
  logName() {
    console.log(this.name)
  }
}

obj.logName();
(0, obj.logName)();

因为用到了window对象,所以不要放在Node环境下执行这段代码。

最简单的方式,直接将这段代码复制丢到chrome控制台下去执行就ok了!

在丢到控制台之前,大家可以自己先来尝试自己思考一下两次分别的打印结果。


image.png

我们可以看到

obj.logName()打印出19Qingfeng(0, obj.logName)()打印出了全局对象上的window.namewang.haoyu

两次打印结果不同的本质原因--函数调用时的this对象指向不同,第一次不用多说指向obj对象自然而然通过this.name打印出的就是19Qingfeg

第二次(0, obj.logName)();执行机制是这样的:

  • 首先逗号操作符的原因,**它会对于左边括号内从左往右求值,最终返回最右边的值也就是返回obj.logName函数内容。

  • 之后右侧的函数调用会调用左侧返回的logName()函数,但是此时相当于直接调用logName()函数体自然而然this就指向了window上。

(0, obj.logName)();
// 本质上它就相当于这样
// 1. 通过逗号操作符获得函数内容
const tem = obj.logName
// 2. 外部调用修改调用者 同时改变this指向
tem()

本质上我们可以通过逗号操作符修改函数内部this指向的改变,类似于call方法的效果。是不是很神奇!

结尾

其实在babel编译后的js代码中,包括许多源码中都会出现(0,parent.fn)()的方式。

一个小小的逗号操作符竟然能修改this指向,不得不说js真的是无奇不有。

希望这个知识点无论是在源码阅读中,还是面试交(吹)流(水)中都可以帮到大家脱口而出逗号操作符是可以改变函数执行时this指向为全局对象的!