ES6标准发布后,前端人员也开发渐渐了解到了es6,但是由于兼容性的问题,仍然没有得到广泛的推广,不过业界也用了一些折中性的方案来解决兼容性和开发体系问题,但大家仍很疑惑,使用ES6会有哪些兼容性问题。

兼容性问题现状

针对ES6的新特性兼容性问题,目前解决的方案是使用语法解析转换工具将es6语法转化为大部分浏览器识别的es5语法,通用的转化方案有babel,traceur,jsx,typescript,es6-shim。当然es6在服务器端也存在兼容性问题,这里由于只考虑到浏览器端的开发,暂不讨论。

考虑到解决方案的多样性,我么会着重考虑以下几个问题:

  1. 兼容性:是否能解决目前常见的所有语法兼容转换;
  2. 易用性:能够很方便的接入到现有的开发构建体系中;
  3. 通用性:业界有较大认可,目前没有很大问题 ;
  4. 持续性:有较权威的团队维护,并能不断更新。

综合四点,我们仍然考虑使用babel作为我们的兼容性解决方案。即使以后需要更换,只需要更换更换工具就可以了,原有代码的写法可以不动。

除了后面三点,我们可能比较关注babel处理es6时的兼容性问题。因为es6里面增加了较多的内容,转换为es5没有对应语法与之对应,所以使用时要尤为注意。为此也没有很好的方法进行判断,只能对于es6里的新增内容进行编译,判断是否可以转为es5语法。

ES6特性 兼容性
箭头函数 支持
类的声明和继承 部分支持,IE8不支持
增强的对象字面量 支持
字符串模板 支持
解构 支持,但注意使用方式
参数默认值,不定参数,拓展参数 支持
let与const 支持
for of IE不支持
iterator, generator 不支持
模块 module、Proxies、Symbol 不支持
Map,Set 和 WeakMap,WeakSet 不支持
Promises、Math,Number,String,Object 的新API 不支持
export & import 支持
生成器函数 不支持
数组拷贝 支持

在es6的新特性中,复杂结构的仍然不支持对es5转换的兼容,具体兼容性可以从下面实例来看~

箭头操作符
//ES6
var fn= (v=>console.log(v));//转换后
//ES5
"use strict";var fn = function fn(v) {return console.log(v);
};

该用法可以放心使用。

类的声明和继承
//类的定义
class Animal {constructor(name) {this.name = name;}sayName() {console.log('My name is '+this.name);}
}
//类的继承
class Programmer extends Animal {constructor(name) {super(name);}program() {console.log("I'm coding...");}
}
//测试我们的类
var animal=new Animal('dummy'),
wayou=new Programmer('wayou');
animal.sayName();//输出 ‘My name is dummy’
wayou.sayName();//输出 ‘My name is wayou’
wayou.program();//输出 ‘I'm coding...’

转换后

//类的定义
'use strict';var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }var Animal = (function () {//ES6中新型构造器function Animal(name) {_classCallCheck(this, Animal);this.name = name;}//类的继承//实例方法_createClass(Animal, [{key: 'sayName',value: function sayName() {console.log('My name is ' + this.name);}}]);return Animal;
})();var Programmer = (function (_Animal) {_inherits(Programmer, _Animal);function Programmer(name) {_classCallCheck(this, Programmer);//直接调用父类构造器进行初始化_get(Object.getPrototypeOf(Programmer.prototype), 'constructor', this).call(this, name);}//测试我们的类_createClass(Programmer, [{key: 'program',value: function program() {console.log("I'm coding...");}}]);return Programmer;
})(Animal);var animal = new Animal('dummy'),wayou = new Programmer('wayou');
animal.sayName(); //输出 ‘My name is dummy’
wayou.sayName(); //输出 ‘My name is wayou’
wayou.program(); //输出 ‘I'm coding...’

转换过程使用了Object.defineProperty,在ie8下不兼容,除此外可以任意使用。

增强的对象字面量
//通过对象字面量创建对象
var human = {breathe() {console.log('breathing...');}
};
var worker = {__proto__: human, //设置此对象的原型为human,相当于继承humancompany: 'freelancer',work() {console.log('working...');}
};
human.breathe();//输出 ‘breathing...’
//调用继承来的breathe方法
worker.breathe();//输出 ‘breathing...’//转换后
//通过对象字面量创建对象
'use strict';var human = {breathe: function breathe() {console.log('breathing...');}
};
var worker = {__proto__: human, //设置此对象的原型为human,相当于继承humancompany: 'freelancer',work: function work() {console.log('working...');}
};
human.breathe(); //输出 ‘breathing...’
//调用继承来的breathe方法
worker.breathe(); //输出 ‘breathing...’

这个可以任意使用。

字符串模板
//产生一个随机数
var num=Math.random();
console.log(`your num is ${num}`);//转换后
//产生一个随机数
"use strict";var num = Math.random();
console.log("your num is " + num);
解构
var [name,gender,age]=['wayou','male','secrect'];//数组解构
console.log('name:'+name+', age:'+age);//输出: name:wayou, age:secrect//转化后
'use strict';var name = 'wayou';
var gender = 'male';
var age = 'secrect';
//数组解构
console.log('name:' + name + ', age:' + age); //输出: name:wayou, age:secrect

此方法可以使用。但是尽量不要使用 var [a, b] = getVal(); 的方式,尽管getVal返回一个数组。因为此时会用到isArray,IE8上不能支持。

参数默认值,不定参数,拓展参数

参数默认值:

function sayHello(age, name='dude'){console.log(`Hello ${name}`);
}
sayHello(12);
转换后'use strict';function sayHello(age) {var name = arguments.length <= 1 || arguments[1] === undefined ? 'dude' : arguments[1];console.log('Hello ' + name);
}
sayHello(12);

不定参数:

//将所有参数相加的函数
function add(...x){return x.reduce((m,n)=>m+n);
}
//传递任意个数的参数
console.log(add(1,2,3));//输出:6
console.log(add(1,2,3,4,5));//输出:15
转换后//将所有参数相加的函数
"use strict";function add() {for (var _len = arguments.length, x = Array(_len), _key = 0; _key < _len; _key++) {x[_key] = arguments[_key];}return x.reduce(function (m, n) {return m + n;});
}
//传递任意个数的参数
console.log(add(1, 2, 3)); //输出:6
console.log(add(1, 2, 3, 4, 5)); //输出:15

扩展参数:

var people=['Wayou','John','Sherlock'];
//sayHello函数本来接收三个单独的参数人妖,人二和人三
function sayHello(people1,people2,people3){console.log(`Hello ${people1},${people2},${people3}`);
}
//但是我们将一个数组以拓展参数的形式传递,它能很好地映射到每个单独的参数
sayHello(...people);//输出:Hello Wayou,John,Sherlock//而在以前,如果需要传递数组当参数,我们需要使用函数的apply方法
sayHello.apply(null,people);//输出:Hello Wayou,John,Sherlock
转换后'use strict';var people = ['Wayou', 'John', 'Sherlock'];
//sayHello函数本来接收三个单独的参数人妖,人二和人三
function sayHello(people1, people2, people3) {console.log('Hello ' + people1 + ',' + people2 + ',' + people3);
}
//但是我们将一个数组以拓展参数的形式传递,它能很好地映射到每个单独的参数
sayHello.apply(undefined, people); //输出:Hello Wayou,John,Sherlock//而在以前,如果需要传递数组当参数,我们需要使用函数的apply方法
sayHello.apply(null, people); //输出:Hello Wayou,John,Sherlock
let与const

letconst完全支持,将都会被转为var,但是要理解letvarconst的区别。

for of
var someArray = [ "a", "b", "c" ];for (v of someArray) {console.log(v);//输出 a,b,c
}//转换后
"use strict";var someArray = ["a", "b", "c"];var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;try {for (var _iterator = someArray[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {v = _step.value;console.log(v); //输出 a,b,c}
} catch (err) {_didIteratorError = true;_iteratorError = err;
} finally {try {if (!_iteratorNormalCompletion && _iterator["return"]) {_iterator["return"]();}} finally {if (_didIteratorError) {throw _iteratorError;}}
}

这里IE下面没有throw,所以无法支持

iterator, generator
var ids = {*[Symbol.iterator]: function () {var index = 0;return {next: function () {return { value: 'id-' + index++, done: false };}};}
};
转换后'use strict';function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }var ids = _defineProperty({}, Symbol.iterator, function () {var index = 0;return {next: function next() {return { value: 'id-' + index++, done: false };}};
});

不建议使用,转换后仍需要浏览器支持。

模块 module、Proxies、Symbol
// point.js
module "point" {export class Point {constructor (x, y) {public x = x;public y = y;}}
}

完全不支持,import也不支持,解析报错,所以建议不使用,使用原来的require

Map,Set 和 WeakMap,WeakSet

MapSetWeakMapWeakSet 在es5中都没有对应的类型与之对应,所以均不支持转换,由浏览器决定兼容性。

Promises、Math,Number,String,Object 的新API

不做语法转换,由浏览器决定兼容性。

export & import
export function myModule(someArg) {return someArg;
}//转换后
"use strict";Object.defineProperty(exports, "__esModule", {value: true
});
exports.myModule = myModule;function myModule(someArg) {return someArg;
}
import * as baz from 'myModule';//转换后
'use strict';function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }var _myModule = require('myModule');var baz = _interopRequireWildcard(_myModule);

所以可以使用exportimport等方法来进行模块的加载处理依赖,同时export使用到了defineProperty,IE8兼容性存在问题。

生成器函数
function* foo() { };
var bar = foo();
bar.next(); // Object {value: undefined, done: true}//转换后
"use strict";var marked0$0 = [foo].map(regeneratorRuntime.mark);
function foo() {return regeneratorRuntime.wrap(function foo$(context$1$0) {while (1) switch (context$1$0.prev = context$1$0.next) {case 0:case "end":return context$1$0.stop();}}, marked0$0[0], this);
};
var bar = foo();
bar.next(); // Object {value: undefined, done: true}

regeneratorRuntime在IE下面不能支持,所以不建议使用。

数组拷贝
const items = [1,2,3];
const itemsCopy = [...items];//转换后
"use strict";var items = [1, 2, 3];
var itemsCopy = [].concat(items);
可以使用

ES6新特性用到的就这些,其它的基本由浏览器本身决定。这部分代码Babel会像处理es5代码一样,不进行加工处理。对于部分ES6的语法,Babel会解析抛错,即使不抛错也不进行处理,建议不使用。

ES6打包体系

使用babel处理了一部分ES6的兼容性转换问题,但是ES6的打包依然必须依赖目前通用的打包管理方案。目前流行的打包方案有以下几种:

  1. webpack+babel+browsify+gulp gulp负责构建、使用webpack打包、browsify管理组件,babel转换 这目前被说的最多的解决方案,因为github上一大堆例子,而且可以很简单的支持到react,但是这样不能形成一个完整的开发体系;另外过于统一,和所在团队使用的技术差异较大。

  2. fis3 + babel + Qjs + lego 选择这样的方案一方面是因为团队目前的主要技术选型,另一方面则是每个工具的特有优势。目前这块仍在不断完善当中。

Babel下的ES6兼容性与规范相关推荐

  1. Nodejs下的ES6兼容性与性能分析

    2019独角兽企业重金招聘Python工程师标准>>> ES6标准发布后,前端人员也开发渐渐了解到了es6,但是由于兼容性的问题,仍然没有得到广泛的推广,不过业界也用了一些折中性的方 ...

  2. express下使用ES6 - dtdxrk - 博客园

    express下使用ES6 1 2 3 4 5 6 7 8 9 //环境切换配置 package.json scripts:{ "service": "NODE_ENV= ...

  3. npm包管理工具与ES6官方模块化规范

    npm介绍 npm有两种含义 : 第一种: 包管理工具node package manager 第二种:npm网站代码托管平台 1.npm 全称node package manager 官方推出的包管 ...

  4. 如何利用babel工具将es6语法转换成es5语法

    如何利用babel工具将es6语法转换成es5语法 一.很多同学疑问既然es6已经出来的了,为很莫写完es6语法还要把他转换成es5,这不是脱裤子放屁吗? ECMAScript 6(ES6)的发展速度 ...

  5. 通过修改程序解决Vista/Win7/Win8下应用程序兼容性问题

    在Vista/Win7/Win8下,有一个系统兼容性助手功能,使得程序在安装完成后或运行时,总是弹出应用程序兼容性助手相关的提示,很是烦人,事实上我们的程序兼容性是没有问题的,只不过是在程序中没有指定 ...

  6. Windows下 Apache+PHP5+MYSQL5+phpmyadmin 规范安装

    < Apache+PHP5+MYSQL5+phpmyadmin> Windows下 Apache+PHP5+MYSQL5+phpmyadmin 规范安装 (绝对原创)     装PHP规范 ...

  7. [日常问题记录]华为模拟器ensp1.2版本在win10下启动virtualbox兼容性问题

    [日常问题记录]华为模拟器ensp1.2版本在win10下启动virtualbox兼容性问题 问题描述 问题描述 启动ensp时提示virtualbox版本不支持,点击virtualbox提示兼容性问 ...

  8. express下使用ES6

    //环境切换配置 package.json scripts:{ "service": "NODE_ENV=production PORT=3000 npm start&q ...

  9. mysql datetime 默认值_老大让我整理下公司内部MySQL使用规范,分享给大家

    作者:白程序员的自习室 链接:https://www.studytime.xin/article/mysql-internal-specifications.html 最近涉及数据库相关操作较多,公司 ...

最新文章

  1. linux_shell 第一章 变量
  2. 做人工智能必看的45篇论文 | 附下载地址
  3. Swift溢出运算符
  4. C语言 矩阵的几种乘法
  5. WIN32 使用事件实现高效生产者消费者模型
  6. is not None与not某某 的区别
  7. 「 每日一练,快乐水题 」682. 棒球比赛
  8. Android应用开发提高系列(4)——Android动态加载(上)——加载未安装APK中的类...
  9. 音视频技术开发周刊 | 237
  10. hdu1466(dp)
  11. linux内存专题,linux内存浅析
  12. Mongo DB命令简介
  13. 路由器刷机后无线模块丢失-竞斗云2.0刷机
  14. 带有第三方工具的Spring Boot Initilizr
  15. 2月第3周业务风控关注|上海网信办复测23个被约谈APP 涉及1号店、小红书等
  16. linuxt gogs搭建
  17. Atitit数据库层次架构表与知识点 attilax 总结
  18. 原生android tv 盒子,MiBox S 小米盒子国际版 | 2019年原生 AndroidTV 推荐 | VLOG31
  19. 第一篇博客:A+B Problem
  20. 深度解析输入偏置电流和输入失调电流的定义来源以及对电路的影响

热门文章

  1. Lucene就是这么简单
  2. 虚拟化学习笔记-虚拟机迁移的分类及原理
  3. ASP.NET性能监控和优化入门
  4. FineUI(专业版)v3.1发布(ASP.NET控件库)!
  5. DEEPIN搭建J2EE时遇到This program requires DISPLAY en...
  6. C# 如何 保存对config文件的修改
  7. PHP 服务器变量 $_SERVER(转)
  8. Windows7下安装配置PHP开发环境
  9. [转]FreeTextBox使用详解
  10. javaweb(09) EL表达式JSTL标签库(jsp相关,了解)