解決ES6不兼容的問題

由于有些瀏覽器版本的發(fā)布是在 es6 定稿和發(fā)布之前的,因此對于老版本的瀏覽器是沒有對 es6 的特性進行兼容的,針對 es6 的兼容問題,許多團隊也做出了相應的開發(fā),將 es6 的語法轉(zhuǎn)換成針對瀏覽器可以識別的 es5 語法,充當一個翻譯官的角色;比較通用的工具有:babel、jsx、traceur、es6-shim 等。
一上車就遇到的梗!!!開發(fā)中,不管你是大佬還是小菜,一定會暈倒ES6的兼容問題,因為現(xiàn)在ES6用的比較潮流的。下面來總結一下不同環(huán)境下有關ES6的相關兼容。

具體ES6兼容解決方案:
ES6瀏覽器的兼容問題
vue cli?解決ES6的兼容問題
小程序中ES6的兼容問題
一、ES6瀏覽器的兼容問題
剛開始的時候一邊解決問題,一邊想著:用 IE8 的都是神經(jīng)病,到后來,我發(fā)現(xiàn)完了,I LOVE IE。
移動端主要用 ES6 + Webpack + Babel 的方式,如果項目并沒有使用任何框架,只引入 zepto 作為一個標準支撐庫。
而 PC 端跟移動端基本保持一致,把 zepto 換成了 jQuery。
//基本的開發(fā)依賴{"devDependencies": {"babel-core": "~6.3.15","babel-loader": "~6.2.0","babel-preset-es2015": "~6.3.13","babel-preset-stage-0": "~6.3.13","babel-runtime": "~6.3.13","extract-text-webpack-plugin": "~0.9.1","less-loader": "~2.2.1","nunjucks-loader": "~1.0.7","style-loader": "~0.10.2","webpack": "~1.12.9","webpack-dev-server": "^1.10.1"}}
Babel 默認只轉(zhuǎn)換轉(zhuǎn)各種 ES5 語法,而不轉(zhuǎn)換新的 API,比如 Promise,以及 Object.assign、Array.from 這些新方法,這時我們需提供 ployfill 來模擬出一個提供原生支持功能的瀏覽器環(huán)境。
1.1、有兩種方法:babel-runtime?和?babel-polyfill
babel-runtime?:
babel-runtime是模擬 ES5 環(huán)境,包含各種分散的 polyfill 模塊,可以在自己的模塊里單獨引入,比如 promise:
import 'babel-runtime/core-js/promise'它們不會在全局環(huán)境添加未實現(xiàn)的方法,只是這樣手動引用每個 polyfill 會非常低效,我們可以借助?Runtime transform?插件來自動化處理這一切。
先 npm 安裝:
npm install babel-plugin-transform-runtime --save-dev然后webpack配置babel-loader:
loader: ["babel-loader"],
query: {
plugins: [
"transform-runtime"
],
presets: ['es2015', 'stage-0']
}babel-polyfill:
babel-polyfill?是針對全局環(huán)境,引入它瀏覽器就好像具備了規(guī)范里定義的完整的特性,一引入,就會跑一個?babel-polyfill?實例。用法如下:
1.安裝 babel-polyfill
npm?install?babel-polyfill?--save2.在入口文件中引用:
import?'babel-polyfill'上面配置基本大部分瀏覽器就可以正常跑,但遇到 IE8,又是一個坑!!!結果在 IE8 上一跑一堆問題。
把?jQuery?換成 1.12.1 ,因為 2.X 已不再支持 IE8--------但是事實部署那么簡單的,兼容性測試過程中會遇到的情況:
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }或者
module.exports = _main2.default;在 IE8 下會直接報”缺少標識符、字符串或數(shù)字”的錯。我們可在對象的屬性上加?''?
function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { 'default': obj };}module.exports = _main2['default'];
并不是 IE8 下對象的屬性必須加?''?,而是?default?作為一個關鍵字,同樣的問題還包括?catch
這兩種情況,可使用?transform-es3-property-literals?和?transform-es3-member-expression-literals?這兩個插件搞定。
總之,平時寫代碼時避免使用關鍵字,或者保留字作為對象的屬性值,尤其是在習慣不加引號的情況下。
1.2、es5-shim、es5-sham
為兼容像 IE8 這樣的老版本瀏覽器,我們引入?es5-shim?作為 polyfill。會遇到?Object.defineProperty?仍提示 "對象不支持此操作"

?es5-shim 明確說明,這個方法的 polyfill 在 IE8 會失敗,因為 IE8 已經(jīng)有個同名的方法,但只是用于 DOM 對象。
同樣的問題還包括?Object.create,上述問題可以再引入 es5-sham 解決.
1.3、addEventListener
項目中直接使用?addEventListener?這個 API,但 IE8 下事件綁定并不是這個方法。
這個問題無需去寫額外的 polyfill。我們已經(jīng)把 jQuery 換成 1.x,所以只需把代碼中?addEventListener?換成?jQuery?寫法就 Ok?
1.4、無法獲取未定義或 null 引用的屬性
這個問題是【轉(zhuǎn)人工】出現(xiàn)的,出現(xiàn)問題不是 IE8,而是 IE9 和 IE10。因為ocs 實例創(chuàng)建失敗,因為沒有調(diào)用父類的構造函數(shù)。通過安裝?transform-es2015-classes?和?transform-proto-to-assign?解決。
配置項加上這兩個插件的配置:
{"plugins": [["transform-es2015-classes", { "loose": true }],"transform-proto-to-assign"]}
1.5、postMessage
雖然?postMessage?是 HTML5 的特性,但 IE8 和 Firefox3 很早就實現(xiàn)了這個 API,當然,跟后來的標準并不一致。這其實也不能怪 IE8。

我們可能會這樣去使用:
parent.postMessage({success: 'ok', name: ‘mirreal’}, ‘*’);但為了兼容 IE8,我們得轉(zhuǎn)成字符串:
parent.postMessage(JSON.stringify({success: 'ok', name: "mirreal"}), ‘*’?
另個需要注意點是:在 IE8 下?window.postMessage?是同步的。

var syncronouse = true;window.onmessage = function () {console.log(syncronouse); // 在 IE8 下會在控制臺打印 true};window.postMessage('test', '*');syncronouse = false;
?1.6、IE8/IE9 的控制臺
IE8 IE9 無法加載。在 IE8 瀏覽器的左下角,好像也是唯一會在頁面提示腳本錯誤的瀏覽器,提示 script error
原因就是我們在代碼中添加了一些控制信息會打印在控制臺,而 IE8/IE9 要開啟 IE Dev Tools 才能使用 console 對象。
切忌把 IE8/9 想成 Chrome/Firefox,以為永遠有 window.console 可用.IE10就改邪歸正,console 不再像段譽的六脈神劍時有時無。
console.log is there in IE8, but the console object isn't created until you open DevTools. Therefore, a call to console.log may result in an error, for example if it occurs on page load before you have a chance to open the dev tools.
只要IE8/9還在一天,console 檢查還是不能少的,事實上,IE8/9 從未死去,所以就像這樣:
if (window.console) {console.log('log here');}
要是有一堆 console.log, console.count, console.error, console.time, console.profile,... 這樣去寫,那還不把人寫到惡心死。
寫個簡單的 console polyfill 吧,檢測是否存在 console,不存在可以常見一個同名的空方法達到不報錯的目的。當然,生產(chǎn)環(huán)境的代碼其實也不會有那么多奇奇怪怪的 console。
17、定義文檔兼容性
X-UA-Compatible 當初是針對 IE8 新加的一個配置。用于為 IE8 指定不同的頁面渲染模式,比如使用 IE7 兼容模式,或者是采用最新的引擎。
現(xiàn)在基本也不需要前者的降級模式,更多的是寫入 IE=edge 支持最新特性。而 chrome=1 則會激活 Google Chrome Frame,前提是你的 IE 安裝過這個插件。
有什么用呢,當然有用,有些 API 是作為新特性存在于 IE8 中的,比如 JSON,不開啟的話就用不了。
為什么要用 X-UA-Compatible?
在 IE8 剛推出的時候,很多網(wǎng)頁由于重構的問題,無法適應較高級的瀏覽器,所以使用 X-UA-Compatible 強制 IE8 采用低版本方式渲染。
比如:使用下面這段代碼后,開發(fā)者無需考慮網(wǎng)頁是否兼容 IE8 瀏覽器,只要確保網(wǎng)頁在 IE6、IE7 下的表現(xiàn)就可以了。
而這段代碼:
IE=edge 告訴 IE 使用最新的引擎渲染網(wǎng)頁,chrome=1 則可以激活 Chrome Frame[1]。
0x0a 條件注釋 or 條件編譯
最后說說 IE 的條件注釋,用法如下:
!????[if?!IE]????The?NOT?operator.?This?is?placed?immediately?in?front?of?the?feature,?operator,?or?subexpression?to?reverse?the?Boolean?meaning?of?the?expression.lt [if lt IE 5.5] The less-than operator. Returns true if the first argument is less than the second argument.lte [if lte IE 6] The less-than or equal operator. Returns true if the first argument is less than or equal to the second argument.gt [if gt IE 5] The greater-than operator. Returns true if the first argument is greater than the second argument.gte [if gte IE 7] The greater-than or equal operator. Returns true if the first argument is greater than or equal to the second argument.( ) [if !(IE 7)] Subexpression operators. Used in conjunction with boolean operators to create more complex expressions.& [if (gt IE 5)&(lt IE 7)] The AND operator. Returns true if all subexpressions evaluate to true| [if (IE 6)|(IE 7)] The OR operator. Returns true if any of the subexpressions evaluates to true.
另外一個類似的東西是在 Javascript 中的條件編譯(conditional compilation)。我們可以使用這段簡單的代碼來做瀏覽器嗅探:
var isIE = /*@cc_on!@*/false在其他瀏覽器中,false 被視為注釋,而在 IE 中,/*@cc_on .... @*/?之間的部分可以被 IE 識別并作為程序執(zhí)行,同時啟用 IE 的條件編譯。
常用變量如下:
* @_win32 如果在 Win32 系統(tǒng)上運行,則為 true。* @_win16 如果在 Win16 系統(tǒng)上運行,則為 true。* @_mac 如果在 Apple Macintosh 系統(tǒng)上運行,則為 true。* @_alpha 如果在 DEC Alpha 處理器上運行,則為 true。* @_x86 如果在 Intel 處理器上運行,則為 true。* @_mc680x0 如果在 Motorola 680x0 處理器上運行,則為 true。* @_PowerPC 如果在 Motorola PowerPC 處理器上運行,則為 true。* @_jscript 始終為 true。* @_jscript_build 包含 JavaScript 腳本引擎的生成號。* @_jscript_version 包含 major.minor 格式的 JavaScript 版本號。
Internet Explorer 11 之前的所有版本的 Internet Explorer 都支持條件編譯。從 Internet Explorer 11 標準模式開始,Windows 8.x 應用商店應用不支持條件編譯。
。。。。
二、vue?cli中解決ES6的兼容問題
有兩種方法:babel-runtime?和?babel-polyfill
npm安裝:
npm install babel-plugin-transform-runtime --save-devwebpack 配置文件的 babel-loader 增加選項:
?loader:?["babel-loader"],query: {plugins: ["transform-runtime"],presets: ['es2015', 'stage-0']}
babel-polyfill 是針對全局環(huán)境的,引入它瀏覽器會具備規(guī)范里定義的完整的特性,一旦引入,就會運行一個 babel-polyfill 實例
//npm安裝npm install babel-polyfill --save//在入口文件中引用:import 'babel-polyfill'
會遇到這樣的問題:vue-cli創(chuàng)建的項目,run 正常,build報錯:Unexpected token name ?i?, expected punc ?;?
這是在 babel 轉(zhuǎn)換的時候發(fā)生的問題
// 在package.json文件里修改"devDependencies": {"uglify-js": "git://github.com/mishoo/UglifyJS2#harmony-v2.8.22","uglifyjs-webpack-plugin": "0.4.3",//在webpack.config.js里面使用?const UglifyJSPlugin = require('uglifyjs-webpack-plugin');new?UglifyJSPlugin()
以替換webpack自帶的UglifyJsPlugin插件可以解決問題。
。。。。https://blog.csdn.net/webKris/article/details/83625673
三、小程序中ES6的兼容問題
1.1、記得勾選上微信開發(fā)工具的ES6轉(zhuǎn)ES5的功能
1.2、引入第三方庫Bluebird?.js或者Runtime.js
。。。。
