最近在看微前端相关的框架,其中import-html-entry有这么一段代码(编译后的兼容版本)

return embedHTMLCache[url] || (embedHTMLCache[url] = fetch(url).then(function (response) {
    return (0, _utils.readResAsString)(response, autoDecodeResponse);
  })

这个(0, _utils.readResAsString)属实是把我看懵了

而github仓库的源码是这样的

return embedHTMLCache[url] || (embedHTMLCache[url] = fetch(url)
    .then(response => readResAsString(response, autoDecodeResponse))

很明显这个是babel之类的插件进行了降级处理,为了提高代码的兼容性,但到底为什么这么做,一番学习(google)后算是搞懂了

首先这个东西叫Comma operator (,)

它会从左到右计算其每个操作数并返回最后一个操作数的值。这可以让我们创建一个复合表达式,在其中对多个表达式求值,复合表达式的最终值是其成员表达式最右边的值。这通常用于为for循环提供多个参数。

let x = 1;

x = (x++, x);

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

x = (2, 3);

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

for (var i = 0, j = 9; i <= 9; i++, j--) {
  console.log('a[' + i + '][' + j + '] = ' + a[i][j]);
}

第一个作用

暴露eval声明的变量

(function() {
  (0, eval)("var foo = 123"); // indirect call to eval, creates global variable
})();
console.log(foo);            // 123

(function() {
  eval("var bar = 123");     // direct call to eval, creates local variable
})();
console.log(bar);            // ReferenceError

比如import-html-entry中有这么一段代码

const geval = (scriptSrc, inlineScript) => {
    const rawCode = beforeExec(inlineScript, scriptSrc) || inlineScript;
    const code = getExecutableScript(scriptSrc, rawCode, proxy, strictGlobal);
    (0, eval)(code);
    afterExec(inlineScript, scriptSrc);
};

这里(0, eval)(code)就是为了把script代码通过eval执行,并且把被执行的代码声明的变量暴露出来
这里的0可以为任意值,只要是间接调用eval,被执行的代码都执行在全局作用域
具体可以看https://stackoverflow.com/questions/14119988/return-this-0-evalthis/14120023

第二个作用

改变this指向(只能改变成全局对象Window或Global)

var obj = {
  method: function() { 
        console.log(this);
        return this;
    }
};
console.log(obj.method() === obj);     // { method: f }, true
console.log((0,obj.method)() === obj); // Window or Global, false

为什么源码要用这种 (0, function)(param) 方式去改变this,而不是 function.call()/apply() 的形式呢?
那是因为这些源码中有时会修改 prototype ,将 call/apply 指向成自己的函数,甚至改变prototype的指向,这样就会导致原型链上方法不可用,那就只好(0, function)(param)了。