给定一个输入文件,如
import { a } from 'b';
function x () {
a()
}
babel 会编译成
'use strict';
var _b = require('b');
function x() {
(0, _b.a)();
}
但是在松散模式下编译时,函数调用输出为 _b.a();
我已经对添加逗号运算符的位置进行了一些研究,希望有评论对其进行解释。负责添加它的代码在这里。
给定一个输入文件,如
import { a } from 'b';
function x () {
a()
}
babel 会编译成
'use strict';
var _b = require('b');
function x() {
(0, _b.a)();
}
但是在松散模式下编译时,函数调用输出为 _b.a();
我已经对添加逗号运算符的位置进行了一些研究,希望有评论对其进行解释。负责添加它的代码在这里。
(0, _b.a)()
确保_b.a
调用该函数时this
将 set 设置为全局对象(或者如果启用了严格模式,则为 to undefined
)。如果您要_b.a()
直接调用,则_b.a
调用this
set to _b
。
(0, _b.a)();
相当于
0; // Ignore result
var tmp = _b.a;
tmp();
(这,
是逗号运算符,请参阅https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator)。
逗号运算符计算其每个操作数(从左到右)并返回最后一个操作数的值。
console.log((1, 2)); // Returns 2 in console
console.log((a = b = 3, c = 4)); // Returns 4 in console
所以,让我们看一个例子:
var a = {
foo: function() {
console.log(this === window);
}
};
a.foo(); // Returns 'false' in console
(0, a.foo)(); // Returns 'true' in console
现在,在foo
方法中,this
等于a
(因为foo
附加到a
)。所以如果你a.foo(
直接调用) ,它会登录false
控制台。
但是,如果你被调用(0, a.foo)()
。该表达式(0, a.foo)
将评估其每个操作数(从左到右)并返回最后一个操作数的值。换句话说,(0, a.foo)
等价于
function() {
console.log(this === window);
}
由于此功能不再附加到任何东西,因此它this
是全局对象window
。这就是为什么它true
在调用时登录控制台的原因(0, a.foo)()
。
以这种迂回方式调用函数:
(throwAwayValueHere, fn)(args);
像这样工作:
throwAwayValueHere, fn
:逗号运算符计算其第一个操作数,丢弃该值,然后计算其第二个操作数并将该值作为其结果。以这种方式调用会在两种情况下产生影响:
1. 如果函数在对象属性上,例如:
(throwAwayValueHere, obj.fn)(args);
它在函数调用期间调用函数而不设置this
为obj
;相反,它被设置为默认值,无论是全局this
值(window
在浏览器上)还是undefined
在严格模式下。
例子:
这就是 Babel 在那里这样做的原因:在原始代码中,调用只是a()
,它a
使用默认this
值调用。做(0, _b.a)()
同样的事情,即使a
是_b
.
2. 如果函数是eval
,它使它成为一个间接的eval
,这意味着它就像在全局范围内进行评估,而不是eval
从本地范围内的字符串运行任意代码的默认行为,使其可以访问所有范围内的变量。
例子: