最近在看微前端相关的框架,其中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)
了。
太高级了 ⌇●﹏●⌇