瀏覽器環(huán)境 兼容運行ES6語法

ES6語言的普及

2015年6月, ES2015(即 ECMAScript 6必尼、ES6) 正式發(fā)布勘究。ES2015 是該語言的一個顯著更新,也是自 2009年 ES5 標準確定后的第一個重大更新览露。伴隨著ES6的普及,大量的js框架都采用了最新的語法譬胎,并且也使前端開發(fā)大量采用工程化開發(fā)方式使用es6語法差牛。但是工程化前端開發(fā)由于其babel編譯的處理,已經(jīng)很好的把ES6的代碼編譯為ES5的版本堰乔,使得各種瀏覽器都能很好的兼容偏化。

瀏覽器的兼容性

然而純?yōu)g覽器端使用ES6語法還是存在瀏覽器支持度的差異,要特殊處理才能正常運行镐侯。

桌面端瀏覽器對ES2015的支持情況

  • Chrome:51 版起便可以支持 97% 的 ES6 新特性侦讨。
  • Firefox:53 版起便可以支持 97% 的 ES6 新特性。
  • Safari:10 版起便可以支持 99% 的 ES6 新特性苟翻。
  • IE:Edge 15可以支持 96% 的 ES6 新特性韵卤。
  • Edge 14 可以支持 93% 的 ES6 新特性。(IE7~11 基本不支持 ES6)

詳細參見:http://kangax.github.io/compat-table/es6/

可以看到IE11又拖了后腿崇猫,對ES6徹底放棄沈条,由Edge 來支撐它的未來。

IE11下有效兼容ES6

那么如何讓純ES6腳本在IE11下運行呢诅炉,還是babel蜡歹,提供了有效的解決辦法
引入兩個腳本:

https://cdn.bootcss.com/babel-core/5.8.35/browser.min.js
該腳本轉(zhuǎn)換的是es6語法層面的語句

https://cdn.bootcss.com/babel-core/5.8.35/browser-polyfill.min.js
該腳本轉(zhuǎn)換了新語法的API屋厘,比如Set Map Promise等的方法

標記腳本塊的 type = "text/babel"

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>IE11 With ES6</title>
    <script src="./browser-polyfill.min.js"></script>
    <script src="./browser.min.js"></script>
    <script type="text/babel">
        const list = ['one', 'two', 'three'];
        list.forEach((item, index) => {
            alert(item + (index + 1));
        });


        let promise = new Promise(function (resolve, reject) {
            alert('Promise');
            resolve();
        });

        promise.then(function () {
            alert('resolved.');
        });


        const items = new Set([1, 2, 3, 4, 5, 5, 5, 5]);
        alert(items.size)


        const map = new Map();

        const k1 = ['a'];
        const k2 = ['a'];

        map.set(k1, 111).set(k2, 222);

        alert(map.get(k2))

    </script>
</head>

<body>

</body>

</html>

那么這里有兩個困惑:

第一:<script type="text/babel"> 和我們平時用的<script type="text/javascript">有什么區(qū)別。

第二:polyfill到底干了什么

我們分別來說明下月而,我們來看一個未壓縮的代碼:https://cdn.bootcss.com/babel-core/5.8.38/browser.js
發(fā)現(xiàn)如下幾個代碼片段:

//頁面加載后汗洒,執(zhí)行runScripts方法
if (global.addEventListener) {
  global.addEventListener("DOMContentLoaded", runScripts, false);
} else if (global.attachEvent) {
  global.attachEvent("onload", runScripts);
}

var runScripts = function runScripts() {
  var scripts = [];
  //識別類型
  var types = ["text/ecmascript-6", "text/6to5", "text/babel", "module"];
  var index = 0;

  /**
   * Transform and execute script. Ensures correct load order.
   */

  var exec = function exec() {
    var param = scripts[index];
    if (param instanceof Array) {
      transform.run.apply(transform, param);
      index++;
      exec();
    }
  };

  /**
   * Load, transform, and execute all scripts.
   */

  var run = function run(script, i) {
    var opts = {};

    if (script.src) {
      transform.load(script.src, function (param) {
        scripts[i] = param;
        exec();
      }, opts, true);
    } else {
      opts.filename = "embedded";
      scripts[i] = [script.innerHTML, opts];
    }
  };

  // Collect scripts with Babel `types`.

  var _scripts = global.document.getElementsByTagName("script");
  //按照類別加載
  for (var i = 0; i < _scripts.length; ++i) {
    var _script = _scripts[i];
    if (types.indexOf(_script.type) >= 0) scripts.push(_script);
  }
  //執(zhí)行
  for (i in scripts) {
    run(scripts[i], i);
  }

  exec();
};

我想我們關注的text/babel就在這里:var types = ["text/ecmascript-6", "text/6to5", "text/babel", "module"];

獲取頁面上標記為以上三項的腳步,然后用transform庫進行加載和翻譯成ES5進行執(zhí)行景鼠。

那么polyfill又干了什么呢仲翎,繼續(xù)閱讀代碼https://cdn.bootcss.com/babel-core/5.8.38/browser-polyfill.js
同樣定位到一段代碼:

$export($export.P, 'Array', {
  // 22.1.3.10 / 15.4.4.18 Array.prototype.forEach(callbackfn [, thisArg])
  forEach: $.each = $.each || methodize(createArrayMethod(0)),
  // 22.1.3.15 / 15.4.4.19 Array.prototype.map(callbackfn [, thisArg])
  map: methodize(createArrayMethod(1)),
  // 22.1.3.7 / 15.4.4.20 Array.prototype.filter(callbackfn [, thisArg])
  filter: methodize(createArrayMethod(2)),
  // 22.1.3.23 / 15.4.4.17 Array.prototype.some(callbackfn [, thisArg])
  some: methodize(createArrayMethod(3)),
  // 22.1.3.5 / 15.4.4.16 Array.prototype.every(callbackfn [, thisArg])
  every: methodize(createArrayMethod(4)),
  // 22.1.3.18 / 15.4.4.21 Array.prototype.reduce(callbackfn [, initialValue])
  reduce: createArrayReduce(false),
  // 22.1.3.19 / 15.4.4.22 Array.prototype.reduceRight(callbackfn [, initialValue])
  reduceRight: createArrayReduce(true),
  // 22.1.3.11 / 15.4.4.14 Array.prototype.indexOf(searchElement [, fromIndex])
  indexOf: methodize(arrayIndexOf),
  // 22.1.3.14 / 15.4.4.15 Array.prototype.lastIndexOf(searchElement [, fromIndex])
  lastIndexOf: function(el, fromIndex /* = @[*-1] */){
    var O      = toIObject(this)
      , length = toLength(O.length)
      , index  = length - 1;
    if(arguments.length > 1)index = Math.min(index, toInteger(fromIndex));
    if(index < 0)index = toLength(length + index);
    for(;index >= 0; index--)if(index in O)if(O[index] === el)return index;
    return -1;
  }
});


var createArrayReduce = function(isRight){
  return function(callbackfn, memo){
    aFunction(callbackfn);
    var O      = IObject(this)
      , length = toLength(O.length)
      , index  = isRight ? length - 1 : 0
      , i      = isRight ? -1 : 1;
    if(arguments.length < 2)for(;;){
      if(index in O){
        memo = O[index];
        index += i;
        break;
      }
      index += i;
      if(isRight ? index < 0 : length <= index){
        throw TypeError('Reduce of empty array with no initial value');
      }
    }
    for(;isRight ? index >= 0 : length > index; index += i)if(index in O){
      memo = callbackfn(memo, O[index], index, this);
    }
    return memo;
  };
};

可以發(fā)現(xiàn)ployfill給Arrary添加了很多新方法,比如createArrayReduce就是實現(xiàn)reduce用的铛漓。

注意

引入以上兩個文件基本就解決了瀏覽器對ES6的大部分支持問題溯香。

不過再次強調(diào):即使使用了轉(zhuǎn)換工具,還是不建議在生產(chǎn)環(huán)境大量地使用瀏覽器對ES6支持度較低的新特性的特性浓恶。畢竟這是在線轉(zhuǎn)換后才執(zhí)行的玫坛,效率比較低。而且隨著瀏覽器對ES6的支持的變化包晰,這些轉(zhuǎn)換腳本也需要經(jīng)常更新湿镀,勢必對后期的維護帶來影響。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末伐憾,一起剝皮案震驚了整個濱河市勉痴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌树肃,老刑警劉巖蒸矛,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異胸嘴,居然都是意外死亡雏掠,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門劣像,熙熙樓的掌柜王于貴愁眉苦臉地迎上來乡话,“玉大人,你說我怎么就攤上這事耳奕“笄啵” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵吮铭,是天一觀的道長时迫。 經(jīng)常有香客問我,道長谓晌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任癞揉,我火速辦了婚禮纸肉,結(jié)果婚禮上溺欧,老公的妹妹穿的比我還像新娘。我一直安慰自己柏肪,他們只是感情好姐刁,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著烦味,像睡著了一般聂使。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谬俄,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天柏靶,我揣著相機與錄音,去河邊找鬼溃论。 笑死屎蜓,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的钥勋。 我是一名探鬼主播炬转,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼算灸!你這毒婦竟也來了扼劈?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤菲驴,失蹤者是張志新(化名)和其女友劉穎荐吵,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谢翎,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡捍靠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了森逮。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片榨婆。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖褒侧,靈堂內(nèi)的尸體忽然破棺而出良风,到底是詐尸還是另有隱情,我是刑警寧澤闷供,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布烟央,位于F島的核電站,受9級特大地震影響歪脏,放射性物質(zhì)發(fā)生泄漏疑俭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一婿失、第九天 我趴在偏房一處隱蔽的房頂上張望钞艇。 院中可真熱鬧啄寡,春花似錦、人聲如沸哩照。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽飘弧。三九已至识藤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間次伶,已是汗流浹背痴昧。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留学少,地道東北人剪个。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像版确,于是被迫代替她去往敵國和親扣囊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Babel是一個廣泛使用的轉(zhuǎn)碼器绒疗,可以將ES6代碼轉(zhuǎn)為ES5代碼侵歇,從而在現(xiàn)有環(huán)境執(zhí)行。 這意味著吓蘑,你可以現(xiàn)在就用 ...
    yichen_china閱讀 1,312評論 0 3
  • babel官網(wǎng) babel 介紹 Babel 是一個通用的多用途 JavaScript 編譯器惕虑。通過 Babel ...
    鋒享前端閱讀 1,820評論 0 10
  • 用命令,可以查看你正在使用的Node環(huán)境對ES6的支持程度磨镶。 使用下面的命令溃蔫,可以查看Node所有已經(jīng)實現(xiàn)的ES6...
    zcwfeng閱讀 727評論 0 2
  • 1、為什么ES6會有兼容性問題琳猫? 由于廣大用戶使用的瀏覽器版本在發(fā)布的時候也許早于ES6的定稿和發(fā)布伟叛,,而到了今天...
    杜小黑妞閱讀 12,852評論 0 5
  • 以前對瀏覽器兼容性問題只是大概知道一些點脐嫂,沒想到這次真正著手去做的時候统刮,還是碰到了很多問題。剛開始的時候一邊解決問...
    沮溺閱讀 27,814評論 2 11