在使用 babel 轉(zhuǎn)換 ES next 代碼的時(shí)候,并不會(huì)將 Symbol 直接轉(zhuǎn)換成 ES5 中對應(yīng)的內(nèi)容,需要引入額外的 polyfill 才能正常工作。
有的團(tuán)隊(duì)為了避免引入這個(gè)額外的 polyfill ,會(huì)選擇不使用 Symbol ,包括通過 babel 生成 Symbol 的特性(比如 for of 等)。
這時(shí)候就會(huì)有個(gè)比較隱蔽的地方需要注意,就是盡量不要讓 babel 生成這樣的代碼:
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
這個(gè)里面包含了一個(gè) Symbol ,為了讓 Symbol 不至于報(bào)錯(cuò),又要想辦法在全局先聲明一下 Symbol 變量,比較丑陋。
目前在實(shí)踐中,發(fā)現(xiàn)這樣的 ES next 代碼會(huì)生成上述代碼:
function fn1() {
if (1) {
let a = 1;
filter(function fn() {
console.log(a);
});
return;
}
}
生成的代碼為:
"use strict";
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
function fn1() {
if (1) {
var _ret = function () {
var a = 1;
filter(function fn() {
console.log(a);
});
return {
v: void 0
};
}();
if ((typeof _ret === "undefined" ? "undefined" : _typeof(_ret)) === "object") return _ret.v;
}
}
這段代碼有什么特征呢?就是在 if 塊中定義了函數(shù),函數(shù)中訪問了 if 塊中的“塊級變量”,并且 if 塊使用了 return 語句。
可以看出,babel 為了保證 if 塊內(nèi)變量的作用域,會(huì)套一個(gè)匿名函數(shù),同時(shí)由于 if 塊中存在 return 返回,所以就用 _ret 來接收匿名函數(shù)的返回值。然后后面為啥會(huì)生成那串長長的對 _ret 的類型判斷代碼,目前還不太清楚,可能要結(jié)合 babel 的內(nèi)部處理邏輯去看了,單從生成的代碼看,這個(gè)完全是多余的。
推而廣之, for 塊等局部非函數(shù)作用域都會(huì)有類似的問題。
實(shí)際上,從代碼編寫規(guī)范角度來看,是不應(yīng)該在這種局部作用域塊里面定義函數(shù)的。函數(shù)應(yīng)該是一段通用的代碼,不應(yīng)該縮在那一小塊里面。