{"id":18260092,"url":"https://github.com/roppa/es6","last_synced_at":"2025-04-08T23:44:45.691Z","repository":{"id":146092631,"uuid":"45427820","full_name":"roppa/es6","owner":"roppa","description":"Demonstrating some ECMA Script 6 (es6) features","archived":false,"fork":false,"pushed_at":"2017-08-25T16:24:08.000Z","size":37,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-14T18:36:29.804Z","etag":null,"topics":["es6","tail-calls"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/roppa.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-11-02T23:02:16.000Z","updated_at":"2017-11-02T17:08:37.000Z","dependencies_parsed_at":"2023-05-14T05:45:34.054Z","dependency_job_id":null,"html_url":"https://github.com/roppa/es6","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roppa%2Fes6","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roppa%2Fes6/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roppa%2Fes6/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roppa%2Fes6/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/roppa","download_url":"https://codeload.github.com/roppa/es6/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247947825,"owners_count":21023058,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["es6","tail-calls"],"created_at":"2024-11-05T10:42:03.563Z","updated_at":"2025-04-08T23:44:45.672Z","avatar_url":"https://github.com/roppa.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[es6fiddle.net](http://www.es6fiddle.net/) is a great resource to try things out in a browser. Check out [the comtability tables](http://kangax.github.io/compat-table/es6/) too.\n\n## Tail Call\n\nDoing recursive calls in Javascript eats up the memory as each call is added onto the call stack. Asymptotically it is O(n). That is because Javascript is not a proper tail recursive language. That is until now. Proper tail recursion causes no memory increase over time when a recursive function is called. In current browsers a recursive function would break if it called itself ~10K. With proper tail call language the asymptotic behaviuour is O(1).\n\n\u003cdl\u003e\n  \u003cdt\u003eTail position\u003c/dt\u003e\n  \u003cdd\u003eThe last instruction to fire before the return statement\u003c/dd\u003e\n  \u003cdt\u003eTail call\u003c/dt\u003e\n  \u003cdd\u003eAn instruction in a tail position that is a function call\u003c/dd\u003e\n  \u003cdt\u003eClose call\u003c/dt\u003e\n  \u003cdd\u003eA call that looks like a tail call but isnt. It maintains the stack as in return 1 + myMethod()\u003c/dd\u003e\n\u003c/dl\u003e\n\nThe main thing to keep in mind when doing recursion is to pass everything to the recursive function - don't leave a scope reference as that will add to the call stack.\n\nAt the moment it is not very widely supported at all :'(\n\n## Variables - Var, Let and Const\n\n### var\n\nYou have to understand what ```var``` does before you understand ```let``` and ```const```. ```var``` is hoisted to the top of the function it is defined in during the compilation stage and it is function scope.\n\nRedeclaring the same variable with ```var``` is a no-ops, meaning it skips the step of allocating disc space for the variable and continues on to assigning a value to it.\n\n### let\n\n ```let``` has a block level scope, rather than function scope. It is ideal in for loops or \"flag\" variables as it is not hoisted like ```var```.\n\nRedefining a variable with let throws an error:\n\n```\nlet a = 0;\nlet a = 1;\n//Syntax error, identifier has already been declared\n```\n\nUsing ```let``` over ```var``` is preferred as it makes your code mirror how it is going to be compiled.\n\n### const\n\n ```const``` as the name suggests is a constant value. Any attempt to reassign the value results in an syntax error. Any redeclaration throws an error.\n\n ```const``` and ```let``` affords more information to the software engineer, rather than seeing 'var' everywhere.\n\n ```const``` is block scope just like ```let```.\n\n### Temporal Dead Zone\n\nYou cant access the variable you have used in your code until it is declared. Sounds weird.\n\n ```let``` is not hoisted, however, memory is allocated when it is compiled. You'll then get a reference error if you try to use that varible before it's been declared. It's much preferred over getting ```undefined``` with ```var```.\n\nAgain, ```let``` adds to the predictablity and readability of your code.\n\n## Strings\n\nStrings now allow templating. We used to concat strings manually using the ```+``` operator. Now we can use the ```\\``` back tick instead of a single or double quote. In that string we can insert varaibles using ```${myVar}```\n\nA cool method on a string is ```repeat```, which, as the name suggests, repeats the string the specified number of times:\n\n```\n\"Bart simpson says I must write this 10 times\".repeat(10);\n```\n\n## Rest parameters\n\nYou know how we have always had access to the ```arguments``` object, which is kind of like an array, but not quite? Rest params are so much better than arguments.\n\nWe used to have to do ```var args = Array.prototype.slice.call(arguments);``` to get an actual array of arguments. The rest param is so much better. Now all we do is name our param but prefixed by a ```...```. As in:\n\n```\nlet showArgs = (...args) =\u003e args;\n```\n\n### Caveats\n\nRest params must be the last in a list of parameters. When it is used it has reference to all the arguments after the last named argument.\n\nYou can't use more than one either.\n\nYou can't use it with ```arguments``` - its either one or the other.\n\nNo default values.\n\n## Spread operators\n\nThe spread operator is ```...```. Looks familiar huh? It is used before an array to pull each value out. It saves you from manually targeting elements of an array.\n\nInstead of using ```apply``` with an array:\n\n```\nlet multiply = (a, b) =\u003e a * b;\nmultiply.apply(null, [5, 5]);\n```\n... you can just call the function:\n\n```\nlet args = [5, 5];\nmultiply(...args);\n```\n\n## Default parameter values\n\nJust like PHP you can now set default values for parameters. If any parameter is falsy, it is set to the default.\n\n```\nlet formatBalance = (balance = 0, name = 'Unknown', currency = '£') =\u003e\n  `${name}, your balance is ${currency}${balance}`;\n```\n\nThis saves us from having to do things like:\n\n```\nfunction myFunction (a, b) {\n  a = a || 0;\n  b = b ? b : 0;\n  //...\n}\n```\n\nDefault parameters are lexically scoped too:\n\n```\nlet count = 0;\nlet increment = (i = count) =\u003e {\n  let count; //lexically scoped\n  return ++count;\n}\n\nincrement(); //NaN\n```\n\nYou can also set a default value to a function call.\n\n## Caveats\n\nYou can't set a default on a Rest param, so no doing:\n\n```\nfunction myFunction (...args = [1,2,3]) { ...\n```\n\nDefault values do no get included in the arguments object:\n\n```\nfunction myFunction (a = 1, b = 2, c = 3) {\n  console.log(arguments.length);\n}\n\nmyFunction(); //0\n```\n\n## Destructuring\n\n\"Destructuring allows you to bind a set of variables to a corresponding set of values anywhere that you can normally bind a value to a single variable\"\n\nDestructuring objects and arrays. With objects we destructure by taking attributes and their values. The thing being destructured MUST be an object.\n\n### Objects\n\n```\nlet getUserById = id =\u003e {\n  return {\n    name: 'Sally',\n    age: 26,\n    location: 'Los Angeles'\n  };\n};\n\n//Destructuring\nlet {name, age, location} = getUserById(1);\n\n//Old style\n//let user = getUserById(1); //so it would be user.name, user.age\n\nconsole.log(`${age} year old ${name} from ${location}`);\n```\n\nNow we have braces on the LHS assignment. The \"Destructuring Pattern\" is the ```{name, age, location}```. The variables in the destructure must reference the attributes targeted in the object.\n\nIf you want different names to those in the object you can do it by specifying the actual name then a colon followed by the alias:\n\n```\nlet {name: n, age: a, location: l} = getUserById(1);\nconsole.log(`${a} year old ${n} from ${l}`);\n```\n\nIf a function takes an object as a parameter then you can target variables that way too:\n\n```\nlet doSomethingWithUserObject = ({name, age, location}) =\u003e {\n  ...\n}\n```\n\nEven better with default values:\n\n```\nlet formatBalance = ({ balance: b = 0, name: n = 'Unknown', currency: c = '£'}) =\u003e\n  `${n}, your balance is ${c}${b}`;\n\nformatBalance({ balance: 10 });\n```\n\n### Arrays\n\nSimilar to Objects we target array elements by their position, and use the square bracket indicating an array rather than a curly brace for an object.\n\n```\nlet winners = ['Peter', 'Paul', 'Mary', 'Jack', 'Sally', 'Jon'];\nlet [winner, second, third,,, last] = winners;\nconsole.log(winner, second, third, last);\n```\n\n## Arrow functions\n\nThis implementation is based on Coffeescript. Coffeescript has two versions of arrow functions - skinny and fat arrows.\n\nAn Arrow function is an anonymous function, meaning it is best not to use it as a method or anywhere you refer to \"this\".\n\nUse parentheses for a function that takes no parameters. If we don't use curly braces for the function body the expression after the ```=\u003e``` is returned. In the case below, ```null``` is always returned:\n\n```\nlet myFunction = () =\u003e null;\n```\n\nIf we are passing one parameter we can omit the parenthesis. This is optional though.\n\n```\nlet myFunction = val =\u003e null;\nmyFunction = (val) =\u003e null;\n```\n\nIf we are passing multiple parameters:\n\n```\nlet myFunction = (a, b, c) =\u003e null;\n```\n\nIf we are using Rest params we must wrap it in parentheses:\n\n```\nlet myFunction = (...params) =\u003e params;\n```\n\nThe return values for all of the above can be exchanged with curly braces and a return statement.\n\n```\nlet myFunction = (...params) =\u003e {\n  return params;\n};\n```\n\nArrow functions by default bind the parameter this to the lexical context. What this means is Arrow functions do not have their own \"this\", instead it is inherited from the \"surrounding\" scope.\n\nBriefly, the parameter \"this\" refers to 5/6 things:\n\n 1. Global context\n 2. Function context (which is global)\n 3. A method i.e. the \"this\" refers to the thing to the left of the dot\n 4. \"call\", where the parameter this is the first argument\n 5. \"apply\", just like #4\n 6. \"bind\", similar to #4 and #5 where the argument is the object to be bound\n\nThe timers ```setTimout``` or ```setInterval``` used to be awkward where we either had to bind the callback function or create a reference such as ```var that = this```. Now we can use an arrow function and the context is maintained.\n\nThis binding can be awkward. With the example below we are adding a method on an object called 'bob'.\n\n```\nlet bob = {\n  name: \"Bob\",\n  sayHello: function () {\n    return `Hi, I'm ${this.name}`;\n  }\n};\n\nbob.sayHello(); //returns \"Hi, I'm bob\"\n```\n\nIf we tried it with an Arrow function we would get an error:\n\n```\nlet bob = {\n  name: \"Bob\",\n  sayHello: () =\u003e {\n    return `Hi, I'm ${this.name}`;\n  }\n};\n\nbob.sayHello(); //Throws an error\n```\n\nLets try it with a constructor function. This works:\n\n```\nlet Person = function (name) {\n  this.name = name;\n  this.sayHello = () =\u003e {\n    return `Hi, I'm ${this.name}`;\n  }\n};\n\nlet bob = new Person('bob');\nbob.sayHello(); //returns \"Hi, I'm bob\"\n```\n\nNow lets try it with ```bind```:\n\n```\nlet Person = function (name) {\n  this.name = name;\n  this.sayHello = function () {\n    return `Hi, I'm ${this.name}`;\n  }\n}\n\nlet bob = new Person('bob');\nlet bill = new Person('bill');\nbob.sayHello(); //Hi, I'm bob\nbob.sayHello.bind(bill)(); //Hi, I'm bob\n```\n\nWe can see that ```bind``` doesn't do as we thought. That's because you can't alter the ```this``` on Arrow functions.\n\nSo the rule is to still use ```function``` when it is suitable. I'm just going to use ```function``` as methods rather than Arrow functions, unless I really don't want the ```this``` parameter to be overridden.\n\n## Classes\n\nI was asked in an interview recently if I used \"classical inheritance\" using ES6 Class or whether I used prototypal inheritance and which one was better. I blushed and was slightly confused. ES6 Class is \"syntactical sugar\" around prototype-based inheritance. The guy didn't really know what he was talking about so I didn't take the job - imagine all that terrible code to inherit, shudder.\n\nSo you know that functions can be used as a constructor, so that it takes the parameter this, constructs a new object, sets it to 'this' and returns it. The convention is that we name the constructor function with an Uppercase first letter so we can distinguish between a function and a constructor function. Now, we can use the class keyword. So instead of this:\n\n```\nfunction Animal () { ...\n```\n\nwe can do:\n\n```\nclass Animal { ...\n```\n\nA class has a constructor function, called ```constructor```.\n\n```\nclass Animal {\n\n  constructor (type) {\n    this.type = type;\n  }\n\n}\n```\n\nIf you don't specify a constructor, it will look through any parent classes, if none then it goes defaults to creating an object and returning it.\n\nMethods are added like this:\n\n```\nclass Dog {\n\n  constructor (name) {\n    this.name = name;\n  }\n\n  annoy () {\n    return \"Bark ... \".repeat(10);\n  }\n\n}\n\n```\n\nIf you want to overide a method and then call the parent method you do so with the ```super``` keyword:\n\n```\ncommunicate () {\n  return super.communicate('woof woof') + '!!';\n}\n```\n\nUnlike function declarations, Classes aren't hoisted so you have to declare it first.\n\n### Getters\n\nSo a getter is a function that returns a value, but you don't call it like a normal function using parenthesis, you just use the property name:\n\n```\nclass Animal {\n\n  constructor (type) {\n    this.type = type;\n  }\n\n  get type () {\n    return this.type;\n  }\n\n}\n\nlet dog = new Animal('mamal');\nconsole.log(dog.type);\n\n```\n\n### Setters\n\nSetters as the name suggests, sets values. It is used just like the getter, a function corresponds to a value. There is reason for caution with setters though. Let's say we had the setter below on the Animal class:\n\n```\n  set type (type) {\n    this.type = type;\n  }\n```\n\nThis would cause an infinite loop, throwing a Range error - maximum stack size exceeded.\n\n## Symbols\n\nThere is a new datatype in Javascript, the Symbol. I didn't grok symbols straight away, but they are pretty cool. Symbols are unique and immutable. They key thing is \"unique\", never giving you the same one twice.\n\nA great use for Symbol is private variables in classes:\n\n```\nlet Animal = (() =\u003e {\n\n  let animalType = Symbol('type');\n\n  return class Animal {\n\n    constructor (name, type) {\n      this.name = name;\n      this[animalType] = type;\n    }\n\n    get type () {\n      return this[animalType];\n    }\n\n  }\n\n}());\n\nlet a = new Animal('dog', 'mamal');\nconsole.log(a.name);\nconsole.log(a.type);\na.type = 'reptile'; //Type error\n\n```\n\n## Class Inheritance\n\nYou can easily extend a class by using the ```extends``` keyword, followed by the ancestor:\n\n```\nclass Dog extends Animal {\n\n  constructor (name) {\n    super('Dog', 'mamal');\n    this.name = name;\n  }\n\n  bark () {\n    return this.communicate('woof woof');\n  }\n\n}\n```\n\n## Promises\n\nSo we've all used libraries like Q or Bluebird - and Promises in jQuery - so the ES6 Promise is a welcome addition to the language. I mean, they are great, but not as great as Observables in Functional Reactive Programming.\n\n\n### The Promise constructor\n\nTo create a promise, you need to pass in the function which takes to parameters, one to handle a successful operation and an error handling function:\n\n```\nreturn new Promise((resolve, reject) =\u003e {\n```\n\n### The Promise Instance\n\nA promise can be in 1 of 4 states:\n\n - fulfilled: resolved - 1\n - rejected: 2\n - pending: either rejected or resolved hasn't happened yet - undefined\n - settled: either rejected or resolved has occured - 1 or 2\n\nOnce you get a promise returned, you call the then the ```then``` method, takes in your resolve, reject functions:\n\n```\nfuncThatReturnsPromise()\n  .then(result =\u003e {\n    return result + ' worked';\n  }, error =\u003e {\n    return 'didn\\'t work';\n  };\n```\n\nYou can do chaining too. If you want to do something with the resolved data you can pass it on:\n\n```\nfuncThatReturnsPromise()\n  .then(function (result) {\n    return result + ', chained once';\n  })\n  .then(function (result) {\n    return result + ', chained twice';\n  })\n  .then(function (result) {\n    return result + ', chained thrice';\n  })\n  .then(function (result) {\n    result.should.eql('later, chained once, chained twice, chained thrice');\n  })\n  .catch((reason) =\u003e {\n    return reason;\n  });\n```\n\nNotice that you can put your reject handler in the ```.catch``` method too. If anything breaks along the chain, it \"bubbles up\" and is caught in the last catch.\n\n### Promise.all\n\nPromise.all takes an array of promises/functions that return a promise, and waits for all of them to complete. The result of which is an array containing all the values returned from the promises:\n\n```\nPromise.all([app.promise.later(), app.promise.later(), app.promise.later()])\n  .then((values) =\u003e {\n    //values should equal ['later', 'later', 'later']\n  });\n```\n\nIf any of them fail then you can catch it as before.\n\n### Promise.race\n\nPromise.race takes an array of promises/functions that return a promise, and uses the first promise that has completed in the resolve function:\n\n```\nPromise.race([app.promise.slow(), app.promise.medium(), app.promise.fast()])\n  .then((result) =\u003e {\n    // result should equal 'fast!'\n  });\n```\n\n## Modules\n\nA module is a single object or a function in a file. The code in the file is made available by the ```export``` keyword.\n\nIt has features from common.js and AMD. It has cycical dependancies, so if you load two or more modules that depend on each other then that is OK.\n\n### Import and export\n\nThe ```export``` object is just that, an object. It can be a function object, and you can attach other things to that object.\n\n```\nexport\n```\n\nTo set the default export:\n\n```\nclass Animal {\n  constructor () {}\n};\nexport default Animal;\n```\n\nAliasing:\n\n```\nclass Animal {\n  constructor () {}\n};\nexport {Animal as Creature};\n```\n\nTo import:\n\n```\nimport Animal from 'Animal';\n```\n\nYou can use aliases.\n\n```\nimport { concat, reduce } from 'underscore';\n```\n\n```\nimport * as _ from 'underscore';\n```\n\n## Programatic Loading - System.import\n\nIt's based on Promises.\n\n```\nSystem.import('Animal').\n  then(Animal =\u003e {\n    //...\n  }).\n  catch(error =\u003e {\n    //...\n  });\n```\n\nSystem methods:\n\n - System.import(module) //returns Promise\n - System.module(module, options) //returns Promise\n - System.set(name, module) //register a new module\n - System.define(name, source, ...options) //\n\nThe module tag: \u003cmodule import=\"animal.js\"\u003e\u003c/module\u003e\n\n## Collections - Maps, Sets and Weakmaps\n\n### Set\n\nA set data structure is a collection, like an array, however it's values are unique.\n\nTo create an instance of a set:\n\n```\nlet alphabet = new Set();\nalphabet.add('a');\nalphabet.add('b');\n...\n```\n\nor you can pass an array as a param to be used for the set:\n\n```\nlet alphabet = new Set(['a', 'b', 'c', 'd']);\n```\n\nSet methods:\n\n```\nalphabet.size; //26\nalphabet.has('a'); //true\nalphabet.has(2); //false\nalphabet.delete(2); //false\nalphabet.clear(); //resets the collection\n```\n\n## Fetch\n\nThe Fetch api is an interface to 'fetch' resources. It will be used to supersede XMLHttpRequest.\n\nWith fetch, the first argument is mandatory (the resource URI), and then it returns a promise.\n\n```\nfetch('http://localhost:3000/authors')\n  .then(data =\u003e JSON.parse(data))\n  .then(console.dir);\n```\n\n## Map\n\nMap is a key/value object.\n\n```\nlet teamA = new Map();\n```\n\nMap methods:\n\n```\nteamA.set('Bob Smith', 'Striker');\n```\n\nYou can use objects as the key:\n\n```\nlet bobSmith = {\n  name: 'Bob Smith',\n  age: 32\n};\nteamA.set(bobSmith, 'Striker');\n```\n\n## Weakmap\n\nWeakmap is like a map but different. It doesn't keep track of the values inside. The thing with a WeakMap is its keys and garbage collection. You can't have primitive values for keys, only objects. And if the WeakMap sees that one of its keys is the only reference to an object, then it will garbage collect it.\n\n```\nlet teamA = new WeakMap();\n```\n\n## Generators\n\nA function will run through its own internal sequence, it cannot 'pause' execution, it runs through each statement sequentially:\n\n```\nfunction basic () {\n  console.log(1);\n  console.log(2);\n  console.log(3);\n}\n\nconsole.log('Basic function');\nbasic();\n//\u003e 1\n//\u003e 2\n//\u003e 3\n```\n\nA generator function looks like ```*function ()```, or ```function* ()```, or ```function *()```. Generator functions are paused and continued by use of the ```yield``` keyword. Think of it like the ```return``` keyword, although there can be multiple ones sequentially.  Generators implement the iterator protocol, so when a generator function is called, an iterator object is returned e.g.:\n\n```\n{ value: 3, done: false }\n{ value: undefined, done: true }\n```\n\n```\nfunction *basicGenerator() {\n  yield console.log(1); // pauses\n  yield console.log(2); // continues on next call\n  yield console.log(3); // ...\n}\n\nconsole.log('Generator function');\nconst iterator = basicGenerator();\niterator.next(); //\u003e 1\niterator.next(); //\u003e 2\niterator.next(); //\u003e 3\niterator.next(); //\u003e\nconsole.log(iterator.next()); //\u003e\n```\n\n## Async and Await\n\n```javascript\nfunction resolveAfter2Seconds(x) {\n  return new Promise(resolve =\u003e {\n    setTimeout(() =\u003e {\n      resolve(x);\n    }, 2000);\n  });\n}\n\nfunction resolveAfter3Seconds(x) {\n  return new Promise(resolve =\u003e {\n    setTimeout(() =\u003e {\n      resolve(x);\n    }, 3000);\n  });\n}\n\nasync function add1(x) {\n  var a = resolveAfter2Seconds(20);\n  var b = resolveAfter3Seconds(30);\n  var aa = await a;\n  console.log('after aa');\n  var bb = await b;\n  console.log('after bb');\n  return x + aa + bb;\n}\n\nadd1(10).then(v =\u003e {\n  console.log(v);  // prints 60 after 2 seconds.\n});\n```\n\n## Resources\n\n- [ECMAScript wiki](http://wiki.ecmascript.org/doku.php)\n- [Frontend Masters ES6 course](https://frontendmasters.com/courses/jsnext-es6)\n- [Exploring ES6](http://exploringjs.com/es6/)\n- [Smashing magazine](http://www.smashingmagazine.com/2015/10/es6-whats-new-next-version-javascript/)\n- [es6 and node compatibility](https://leanpub.com/understandinges6/read/#leanpub-auto-browser-and-nodejs-compatibility)\n- [Mozilla deveoper](https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_6_support_in_Mozilla)\n- [Mozilla hacks arrow functions](https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/)\n- [ES6 Katas](http://es6katas.org/)\n- [brendaneich.com](https://brendaneich.com/tag/javascript-ecmascript-harmony-coffeescript/)\n- [uxebu.com](http://www.uxebu.com/blog/2015/06/learn-ecmascript-6-in-a-different-way/)\n- [wintellect.com](http://www.wintellect.com/devcenter/nstieglitz/5-great-features-in-es6-harmony)\n- [lukehoban on Github](https://github.com/lukehoban/es6features/blob/master/README.md)\n- [coryrylan.com](http://coryrylan.com/blog/javascript-es6-class-syntax)\n- [Eric](https://medium.com/javascript-scene/7-surprising-things-i-learned-writing-a-fibonacci-generator-4886a5c87710)\n- [Mozilla docs](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Symbol)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froppa%2Fes6","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Froppa%2Fes6","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froppa%2Fes6/lists"}