JS中奇怪的(0,fn)()
前言
现代前端开发,大都离不开一些工程化的工具,比如webpack
,babel
。我们通过这些工具来提高我们的开发工作。让我们优雅的代码可以被引擎执行。
但是当我们打开被编译后的js代码,会发现一个奇怪的语法,比如babel就会进行如下的代码转换
输入:
import {join} from "lodash";
function b(){
return join()
}
Babel编译后输出:
"use strict";
var _lodash = require("lodash");
function b() {
return (0, _lodash.join)();
}
奇怪的地方就在(0, _lodash.join)()
。
开始时呢,并没有考虑那么深,觉得只是一个函数调用而已。还会吐槽说,为什么不直接调用。
本着求实的态度。翻阅了一些资料,才明白。
首先呢,这里涉及到几个问题:
- 逗号操作符
- 函数中的this
一一来分析
逗号操作符
前面那段奇怪的代码,就使用了这个运算符。
根据MDN JavaScript的文档,可以发现。
MDN:
逗号操作符 对它的每个操作数求值(从左到右),并返回最后一个操作数的值
当你想要在期望一个表达式的位置包含多个表达式时,可以使用逗号操作符。这个操作符最常用的一种情况是:
for
循环中提供多个参数。
简单的来说,逗号在这里,只是让表达式(0,_lodash.join)
返回这个函数引用。
为什么不直接调用呢?
继续分析
函数调用的原理
我们都知道在js中函数的this
是指向函数的调用者的,也就是谁调用了函数,那么this
就指向谁。
当直接调用的时候,函数的this
就是全局对象(window
或global
)
在来看看上面的输入代码:
import {join} from "lodash";
function b(){
return join()
}
我们在执行join
函数的时候,this
应该是全局对象
(window或global)。
import
打包后babel给模块添加了名字_lodash
,是通过_lodash
来调用join
函数的。
//模块化打包输出一个模块引用
var _lodash = require("lodash");
//通过模块引用来调用函数
(0, _lodash.join)();
这个时候join
函数的this就变成_lodash,而不是源代码里的全局对象了;
其实就是相当于:
0;
var fn=_lodash.join;
fn()
所以这里更官方的说法就是,模块化打包后方便切断模块化函数调用时的this绑定问题;
也就是说,
(0, _lodash.join)();
确保了this
指向源代码里的指向。
如果我们把源代码写成这样:
import lodash from "lodash";
function b(){
return join.join()
}
那么输出的就不是上面的那种方式了:
"use strict";
var _lodash = _interopRequireDefault(require("lodash"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function b() {
return join.join();
}
总结
(0,fn)()
这种方式是为了保证源代码里的函数调用的时的this指向问题(0,fn)()
这种方式更加的优雅,简单。,
操作符的运用