Article by Imweb Ouven source: imweb community without consent, prohibit republication

After the release of ES6 standard, front-end staff also gradually learned about ES6, but due to compatibility problems, it has not been widely promoted, but the industry has also used some neutral solutions to solve compatibility and development system problems, but everyone is still very confused, using ES6 will have what compatibility problems.

I. Current situation of compatibility problems

In view of the compatibility problem of new ES6 features, the current solution is to use syntax parsing and conversion tools to convert ES6 syntax into ES5 syntax recognized by most browsers. The common conversion schemes include Babel, Traceur, JSX, typescript, and ES6-Shim. Of course, es6 also has compatibility issues on the server side, which will not be discussed here because only the browser side is considered. Here are some common solutions and es6 compatibility comparisons

Github.com/babel/babel… Kangax.github. IO /compat-tabl…

Considering the diversity of solution, I will focus on the following questions: 1, compatibility: whether can solve the current common grammar is compatible with all convert 2, ease of use: to be able to easily access to the build system for the development of the existing 3, generality: the industry a greater recognition, there is no big question 4, sustainability: Have more authoritative team maintenance, and can update constantly

Together, we are still considering Babel as our compatibility solution. Even if you need to replace it later, you only need to replace the tool, and the original code writing method can not be changed. Aside from the last three points, we might be concerned about Babel’s compatibility with ES6. Because es6 has added a lot of content, conversion to ES5 does not have the corresponding syntax, so use special care. There is no good way to determine this, other than to compile new content in ES6 and determine whether it can be converted to ES5 syntax.

A compatibility list of new ES6 features under Babel

ES6 features compatibility
Arrow function support
Class declaration and inheritance Partial support, IE8 does not support
Enhanced object literals support
String template support
deconstruction Yes, but be careful how you use it
Parameter Default value, indefinite parameter, extended parameter support
Let the const support
for of IE does not support
iterator, generator Does not support
Module, Proxies, Symbol Does not support
Map, Set and WeakMap, WeakSet Does not support
Promises, Math, Number, String, Object API Does not support
export & import support
Generator function Does not support
Copy an array support

Among the new es6 features, complex architectures still do not support compatibility with ES5 transformations, as shown in the following examples

1.1 Arrow operators

The arrow operator can describe a function succinctly

// ES6
var fn= (v=>console.log(v))
Copy the code

After the transformation

 
"use strict";

var fn = function fn(v) {
  return console.log(v);
};
Copy the code

This usage is safe to use.

1.2 Class declaration and inheritance

Constructor (name) {this.name = name; } // Instance method sayName() {console.log('My name is '+this.name); Constructor () {constructor() {constructor() {constructor() {constructor() {constructor() {constructor() {constructor(); } program() { console.log("I'm coding..." ); Var animal=new animal ('dummy'), wayou=new Programmer('wayou'); animal.sayName(); // output 'My name is dummy' wayou.sayname (); // Output 'My name is wayou' wayou.program(); // Output 'I'm coding... 'Copy the code

After the transformation

'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 () { 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(); wayou.sayName(); wayou.program();Copy the code

DefineProperty was used during the conversion, which is not compatible with IE8 and can be used anywhere else

1.3 Enhanced object literals


var human = {
    breathe() {
        console.log('breathing...');
    }
};
var worker = {
    __proto__: human, 
    company: 'freelancer',
    work() {
        console.log('working...');
    }
};
human.breathe();

worker.breathe();
Copy the code

After the transformation


'use strict';

var human = {
    breathe: function breathe() {
        console.log('breathing...');
    }
};
var worker = {
    __proto__: human, 
    company: 'freelancer',
    work: function work() {
        console.log('working...');
    }
};
human.breathe(); 

worker.breathe(); 
Copy the code

This can be used arbitrarily

1.4 String Templates


var num=Math.random();
console.log(`your num is ${num}`);
Copy the code

After the transformation


"use strict";

var num = Math.random();
console.log("your num is " + num);
Copy the code

1.5 deconstruction

var [name,gender,age]=['wayou','male','secrect'];
console.log('name:'+name+', age:'+age);
Copy the code

After the transformation

'use strict';

var name = 'wayou';
var gender = 'male';
var age = 'secrect';

console.log('name:' + name + ', age:' + age); 
Copy the code

This method can be used. But try not to use var [a, b] = getVal(); Although getVal returns an array. IsArray is used, which is not supported on IE8.

1.6 Parameter Default value, indefinite parameter, and extended parameter

function sayHello(age, name='dude'){
    console.log(`Hello ${name}`);
}
sayHello(12);
Copy the code

After the transformation

'use strict';

function sayHello(age) {
    var name = arguments.length <= 1 || arguments[1] === undefined ? 'dude' : arguments[1];

    console.log('Hello ' + name);
}
sayHello(12);
Copy the code
function add(... x){ return x.reduce((m,n)=>m+n); } the console. The log (add (1, 2, 3)); The console. The log (add (1, 2, 3, 4, 5));Copy the code

After the transformation


"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)); 
console.log(add(1, 2, 3, 4, 5)); 
Copy the code
var people=['Wayou','John','Sherlock']; function sayHello(people1,people2,people3){ console.log(`Hello ${people1},${people2},${people3}`); } sayHello(... people); sayHello.apply(null,people);Copy the code

After the transformation

'use strict';

var people = ['Wayou', 'John', 'Sherlock'];

function sayHello(people1, people2, people3) {
    console.log('Hello ' + people1 + ',' + people2 + ',' + people3);
}

sayHello.apply(undefined, people); 


sayHello.apply(null, people); 
Copy the code

Parameter default value, variable parameter, extended parameter can be used fully

1.7 the let and const

Let and const are fully supported and will both be converted to var, but understand the difference between let, var, and const.

1.8 the for of

var someArray = [ "a", "b", "c" ];

for (v of someArray) {
    console.log(v);
}
Copy the code

After the transformation

"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); 
  }
} catch (err) {
  _didIteratorError = true;
  _iteratorError = err;
} finally {
  try {
    if (!_iteratorNormalCompletion && _iterator["return"]) {
      _iterator["return"]();
    }
  } finally {
    if (_didIteratorError) {
      throw _iteratorError;
    }
  }
}
Copy the code

There is no throw under IE, so it cannot be supported

1.9 the iterator, the generator

var ids = { *[Symbol.iterator]: function () { var index = 0; return { next: function () { return { value: 'id-' + index++, done: false }; }}; }};Copy the code

After the transformation

'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 }; }}; });Copy the code

Not recommended. Browser support is still required after conversion

1.10 Module module, Proxies, Symbol

module "point" { export class Point { constructor (x, y) { public x = x; public y = y; }}}Copy the code

It is not supported at all, import is not supported, parsing error, so it is recommended not to use, use the original require

1.11 Map, Set and WeakMap, WeakSet

Map, Set and WeakMap and WeakSet have no corresponding types corresponding to them in ES5, so they do not support conversion, and compatibility is determined by the browser

Promises, Math, Number, String, Object API

No syntax conversions are made and compatibility is determined by the browser

1.13 the export & import

export function myModule(someArg) {
  return someArg;
}
Copy the code

After the transformation

"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.myModule = myModule;

function myModule(someArg) {
  return someArg;
}
Copy the code
import * as baz from 'myModule';
Copy the code

After the transformation

'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);Copy the code

Therefore, methods such as export and import can be used for module loading processing dependency, and export uses defineProperty, which causes compatibility problems in IE8.

1.14 Generator functions

function* foo() { };
var bar = foo();
bar.next(); 
Copy the code

After the transformation

"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}
Copy the code

RegeneratorRuntime is not supported in IE, so it is not recommended.

The new ES6 features use these, and the rest is largely up to the browser itself. This part of the code is left untouched by Babel as it is by ES5 code. For some ES6 grammars, Babel will parse the throw error and will not handle it even if it is not thrown. It is recommended not to use it. 1.15 Array Copy

Const items = [1, 2, 3]; const itemsCopy = [...items];Copy the code

After the transformation

"use strict";

var items = [1, 2, 3];
var itemsCopy = [].concat(items);
Copy the code

You can use

ES6 packaging system

Some of the ES6 compatibility conversion issues are addressed using Babel, but ES6 packaging still has to rely on the currently common package management scheme. Gulp is responsible for building and using WebPack packaging and browsify management components. Babel is the most talked about solution at present, because there are a lot of examples on Github. React can be easily supported, but this does not form a complete development system; In addition, it is too unified and differs greatly from the technology used by the team.

This approach was chosen because of both the team’s current primary technology selection and the unique strengths of each tool. This is still a work in progress.

Third, summary

So using ES6 this scheme for actual development necessity still need to consider whether there is a certain, because ES6 higher characteristic in es5 not to replace the corresponding features, even can replace use some complex custom function to do, and some can implement the conversion feature still less, and write up is very concise, This is also a big advantage of the ES6.

In addition, in order to make Babel useful in actual development, we have compiled a specification for the ES6 part:

Github.com/ouvens/ecma…