├── .gitignore
├── README.md
├── index.html
├── package.json
├── src
├── Point.js
├── arbitraryArguments.js
├── arrow.js
├── async.js
├── classes.js
├── defaultParameters.js
├── destructuring.js
├── exports.js
├── forEach.js
├── functionExpression.js
├── generators.js
├── iife.js
├── imports.js
├── letConst.js
├── main.js
├── maps.js
├── multipleReturnValues.js
├── namedParameters.js
├── optionalNamedParameters.js
├── promises.js
├── sets.js
├── spread.js
├── stringInterpolation.js
├── strings.js
├── sumOfSquares.js
└── symbols.js
└── webpack.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/*
2 | bundle.js
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # es6-deep-dive
2 |
3 | Repository containing examples highlighting differences and improvements between ES5 and ES6.
4 |
5 | # Running examples
6 |
7 | To run the examples contained in this repository:
8 |
9 | # Install the dependencies
10 | npm install
11 |
12 | # Run Webpack
13 | npm run watch
14 |
15 | Note: For OS X users, you'll have to prepend `sudo` to the above commands.
16 |
17 | Once Webpack is running, simply open `index.html`.
18 |
19 | # LICENSE
20 |
21 | The MIT License (MIT)
22 |
23 | Copyright (c) 2015 David Leonard
24 |
25 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
26 |
27 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
28 |
29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 |
31 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Webpack ES6 Demo
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "es6-deep-dive",
3 | "version": "0.0.1",
4 | "description": "ES5 -> ES6 Deep Dive",
5 | "main": "main.js",
6 | "devDependencies": {
7 | "babel-core": "*",
8 | "babel-loader": "*",
9 | "node-libs-browser": "*",
10 | "webpack": "*"
11 | },
12 | "scripts": {
13 | "watch": "webpack --watch"
14 | },
15 | "repository": {
16 | "type": "git",
17 | "url": "https://github.com/DrkSephy/es6-deep-dive.git"
18 | },
19 | "keywords": [
20 | "es5",
21 | "es6",
22 | "webpack"
23 | ],
24 | "author": "David Leonard",
25 | "license": "MIT",
26 | "bugs": {
27 | "url": "https://github.com/DrkSephy/es6-deep-dive/issues"
28 | },
29 | "homepage": "https://github.com/DrkSephy/es6-deep-dive",
30 | "dependencies": {
31 | "babel-preset-es2015": "^6.16.0"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Point.js:
--------------------------------------------------------------------------------
1 | class Point {
2 |
3 | constructor(x, y, z) {
4 | this.x = x;
5 | this.y = y;
6 | this.z = z;
7 | }
8 |
9 | toString() {
10 | return ' (' + this.x + ' , ' + this.y + ' , ' + this.z + ')';
11 | }
12 | }
13 | export default Point;
--------------------------------------------------------------------------------
/src/arbitraryArguments.js:
--------------------------------------------------------------------------------
1 | // Arbitrary amount of arguments using ES5
2 | function logAllArguments() {
3 | for (var i=0; i < arguments.length; i++) {
4 | console.log(arguments[i]);
5 | }
6 | }
7 |
8 | // In ES6, we can use a rest parameter to specify an
9 | // arbitrary amount of arguments
10 | function logAllArguments(...args) {
11 | for (let arg of args) {
12 | console.log(arg);
13 | }
14 | }
--------------------------------------------------------------------------------
/src/arrow.js:
--------------------------------------------------------------------------------
1 | // ES5
2 | // Trying to prefix this.name from Person won't work due to the scoping
3 | // and the value of this being changed
4 |
5 | function Person(name) {
6 | this.name = name;
7 | }
8 |
9 | Person.prototype.prefixName = function (arr) {
10 | return arr.map(function (character) {
11 | return this.name + character;
12 | });
13 | };
14 |
15 | // ES5 Solution 1: Store the this pointer
16 |
17 | function Person(name) {
18 | this.name = name;
19 | }
20 |
21 | Person.prototype.prefixName = function (arr) {
22 | var that = this;
23 | return arr.map(function (character) {
24 | return that.name + character;
25 | });
26 | };
27 |
28 | // ES5 Solution 2: Pass the value that this should be
29 | // when the callback is invoked
30 |
31 | function Person(name) {
32 | this.name = name;
33 | }
34 |
35 | Person.prototype.prefixName = function (arr) {
36 | return arr.map(function (character) {
37 | return this.name + character;
38 | }, this);
39 | }
40 |
41 | // ES5 Solution 3: Bind the correct value of this
42 | function Person(name) {
43 | this.name = name;
44 | }
45 |
46 | Person.prototype.prefixName = function (arr) {
47 | return arr.map(function (character) {
48 | return this.name + character;
49 | }.bind(this));
50 | }
51 |
52 | // ES6 Solution: Use the Arrow function!
53 | function Person(name) {
54 | this.name = name;
55 | }
56 |
57 | Person.prototype.prefixName = function(arr) {
58 | return arr.map((character) => {
59 | return this.name + character;
60 | });
61 | };
62 |
63 | // ES6 Function Expressions versus arrow functions
64 | const arr = [1, 2, 3, 4, 5];
65 | const squares = arr.map(x => x * x);
66 |
67 | // Traditional function expression:
68 | const squares = arr.map(function (x) { return x * x });
--------------------------------------------------------------------------------
/src/async.js:
--------------------------------------------------------------------------------
1 | // Explaining ES7 Async await
2 |
3 | var request = require('request');
4 |
5 | function getJSON(url) {
6 |
7 | request(url, function(error, response, body) {
8 | return body;
9 | });
10 | }
11 |
12 | function main() {
13 | var data = getJSON('http://some_api/item1');
14 | console.log(data); // Undefined
15 | }
16 |
17 | main();
18 |
19 | // Solution? Async/await
20 | var request = require('request');
21 |
22 | function getJSON(url) {
23 | return new Promise(function(resolve, reject) {
24 | request(url, function(error, response, body) {
25 | resolve(body);
26 | });
27 | });
28 | }
29 |
30 | async function main() {
31 | var data = await getJSON();
32 | console.log(data); // NOT undefined!
33 | }
34 |
35 | main();
36 |
37 |
--------------------------------------------------------------------------------
/src/classes.js:
--------------------------------------------------------------------------------
1 | // ES6 example of a class
2 |
3 | // ES5 Base Class
4 | function Person(name, age, gender) {
5 | this.name = name;
6 | this.age = age;
7 | this.gender = gender;
8 | }
9 |
10 | Person.prototype.incrementAge = function () {
11 | return this.age += 1;
12 | };
13 |
14 | // Base class
15 | class Person {
16 | constructor(name, age, gender) {
17 | this.name = name;
18 | this.age = age;
19 | this.gender = gender;
20 | }
21 |
22 | incrementAge() {
23 | this.age += 1;
24 | }
25 | }
26 |
27 | // Extended Classes in ES5
28 | function Employee(name, title) {
29 | Person.call(this, name); // super(name)
30 | this.title = title;
31 | }
32 | Employee.prototype = Object.create(Person.prototype);
33 | Employee.prototype.constructor = Employee;
34 | Employee.prototype.describe = function () {
35 | return Person.prototype.describe.call(this) // super.describe()
36 | + ' (' + this.title + ')';
37 | };
38 |
39 | function Personal(name, age, gender, occupation, hobby) {
40 | Person.call(this, name, age, gender);
41 | this.occupation = occupation;
42 | this.hobby = hobby;
43 | }
44 |
45 | Personal.prototype = Object.create(Person.prototype);
46 | Personal.prototype.constructor = Personal;
47 | Personal.prototype.incrementAge = function () {
48 | return Person.prototype.incrementAge.call(this) += 1;
49 | }
50 |
51 | // Extended Class
52 | class Personal extends Person {
53 | constructor(name, age, gender, occupation, hobby) {
54 | super(name, age, gender);
55 | this.occupation = occupation;
56 | this.hobby = hobby;
57 | }
58 |
59 | incrementAge() {
60 | super.incrementAge();
61 | this.age += 20;
62 | console.log(this.age);
63 | }
64 | }
65 |
66 | const person = new Personal('David', 25, 'male', 'metalhead', 'game development');
67 | person.incrementAge();
68 |
69 |
70 | let _counter = new WeakMap();
71 | let _action = new WeakMap();
72 | class Countdown {
73 | constructor(counter, action) {
74 | _counter.set(this, counter);
75 | _action.set(this, action);
76 | }
77 | dec() {
78 | let counter = _counter.get(this);
79 | if (counter < 1) return;
80 | counter--;
81 | _counter.set(this, counter);
82 | if (counter === 0) {
83 | _action.get(this)();
84 | }
85 | }
86 | }
87 |
88 | // Simulating private data using WeakMaps
89 | let _age = new WeakMap();
90 | class Person {
91 | constructor(age) {
92 | _age.set(this, age);
93 | }
94 |
95 | incrementAge() {
96 | let age = _age.get(this);
97 | if(age > 50) {
98 | console.log('Midlife crisis');
99 | }
100 | }
101 | }
102 |
103 | > const person = new Person(25);
104 | > person.incrementAge();
105 | > Reflect.ownKeys(person); // []
--------------------------------------------------------------------------------
/src/defaultParameters.js:
--------------------------------------------------------------------------------
1 | // Handling default parameters in ES5
2 | function addTwoNumbers(x, y) {
3 | x = x || 0;
4 | y = y || 0;
5 | return x + y;
6 | }
7 |
8 | // Handling default parameters in ES6
9 | function addTwoNumbers(x=0, y=0) {
10 | return x + y;
11 | }
12 |
13 | addTwoNumbers(2, 4); // 6
14 | addTwoNumbers(2); // 2
15 | addTwoNumbers(); // 0
--------------------------------------------------------------------------------
/src/destructuring.js:
--------------------------------------------------------------------------------
1 | // Destructuring allows us to bind properties to as many variables
2 | // as we need.
3 |
4 | // Example for Objects
5 | var luke = { occupation: 'jedi', father: 'anakin' }
6 | var {occupation, father} = luke;
7 | console.log(occupation); // 'jedi'
8 | console.log(father); // 'anakin'
9 |
10 | // Example for Arrays
11 | var [a] = [10]
12 | console.log(a); // 10
13 |
14 | // Using Destructuring to interact with objects easier
15 | function getCoords () {
16 | return {
17 | x: 10,
18 | y: 22
19 | }
20 | }
21 |
22 | var {x, y} = getCoords()
23 | console.log(x); // 10
24 | // <- 10
25 | console.log(y); // 22
26 |
--------------------------------------------------------------------------------
/src/exports.js:
--------------------------------------------------------------------------------
1 | // CommonJS exports in ES5
2 | module.exports = 1
3 | module.exports = { foo: 'bar' }
4 | module.exports = ['foo', 'bar']
5 | module.exports = function bar () {}
6 |
7 | // Exports in ES6
8 | export default 1
9 | export default { foo: 'bar' }
10 | export default ['foo', 'bar']
11 | export default function bar () {}
12 |
13 | // Named Exports in CommonJS
14 | module.exports.name = 'David';
15 | module.exports.age = 25;
16 |
17 | // Named Exports in ES6
18 | // NOTE: Exports are binding, changing the variable used when
19 | // imported would affect the public interface itself
20 | export var name = 'David';
21 | export var age = 25;
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/forEach.js:
--------------------------------------------------------------------------------
1 | // Array iteration using forEach in ES5
2 | arr.forEach(function (item) {
3 | console.log(item);
4 | });
5 |
6 | // Iterate over an array using ES6
7 | let arr = ['a', 'b', 'c'];
8 | for (let item of arr) {
9 | console.log(item);
10 | }
11 |
12 | // Get both index and value using .entries and destructuring
13 | for (let [index, item] of arr.entries()) {
14 | console.log(index+'. '+item);
15 | }
--------------------------------------------------------------------------------
/src/functionExpression.js:
--------------------------------------------------------------------------------
1 | function Component {
2 | var _this = this; // Copy instance of this pointer
3 | var button = document.getElementById('myButton');
4 | button.addEventListener('click', function () {
5 | console.log('CLICK');
6 | _this.handleClick(); // Inner instance of this
7 | });
8 | }
9 |
10 | // Extend prototype with handleClick function
11 | UiComponent.prototype.handleClick = function () {
12 | ···
13 | };
14 |
15 | // Arrow functions don't shadow (this), which is lexical to current scope
16 | class Component {
17 | constructor() {
18 | let button = document.getElementById('myButton');
19 | button.addEventListener('click', () => {
20 | console.log('CLICK');
21 | this.handleClick(); // Fat arrow handles this for us
22 | });
23 | }
24 |
25 | // extend Component class with handleClick function
26 | handleClick() {
27 | ···
28 | }
29 | }
--------------------------------------------------------------------------------
/src/generators.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Notes on ES6 Generators.
3 | */
4 |
5 | function* sillyGenerator() {
6 | yield 1;
7 | yield 2;
8 | yield 3;
9 | yield 4;
10 | }
11 |
12 | var generator = sillyGenerator();
13 | var value = generator.next();
14 | > console.log(value); // { value: 1, done: false }
15 | > console.log(value); // { value: 2, done: false }
16 | > console.log(value); // { value: 3, done: false }
17 | > console.log(value); // { value: 4, done: false }
18 |
19 | // Note how the generator is technically not done iterating
20 | // It will return { value: undefined, done: true} on next
21 | // iteration.
22 |
23 | // Can we use return? Using for...of
24 | function* sillyGenerator() {
25 | yield 1;
26 | yield 2;
27 | yield 3;
28 | yield 4;
29 | return 5;
30 | }
31 |
32 | for(let val of sillyGenerator()) {
33 | console.log(val); // 1, 2, 3, 4
34 | }
35 |
36 | // We'll never get 5, since we exposed no method to use .next()
37 |
38 |
39 | // Actual generator example
40 | function* factorial(){
41 | let [current, total] = [0, 1];
42 |
43 | while (true){
44 |
45 | yield total;
46 |
47 | current++;
48 | total = total * current;
49 | }
50 | }
51 |
52 | for (let n of factorial()) {
53 | console.log(n);
54 | if(n >= 100000) {
55 | break;
56 | }
57 | }
58 |
59 | // Hiding asynchronousity with Generators
60 | function request(url) {
61 | getJSON(url, function(response) {
62 | generator.next(response);
63 | });
64 | }
65 |
66 | function* getData() {
67 | var entry1 = yield request('http://some_api/item1');
68 | var data1 = JSON.parse(entry1);
69 | var entry2 = yield request('http://some_api/item2');
70 | var data2 = JSON.parse(entry2);
71 | }
72 |
73 | // Upgrading our generator using promises
74 | function request(url) {
75 | // Note: returning a promise now!
76 | return new Promise( function(resolve,reject){
77 | makeAjaxCall( url, resolve );
78 | } );
79 | }
80 |
81 | // This will yield a promise
82 | function request(url) {
83 | return new Promise((resolve, reject) => {
84 | getJSON(url, resolve);
85 | });
86 | }
87 |
88 | // Construct a function to control the generator
89 | function iterateGenerator(gen) {
90 | var generator = gen();
91 | var ret;
92 | (function iterate(val) {
93 | ret = generator.next();
94 | if(!ret.done) {
95 | ret.value.then(iterate);
96 | } else {
97 | setTimeout(function() {
98 | iterate(ret.value);
99 | });
100 | }
101 | })();
102 | }
103 |
104 | iterateGenerator(function* getData() {
105 | var entry1 = yield request('http://some_api/item1');
106 | var data1 = JSON.parse(entry1);
107 | var entry2 = yield request('http://some_api/item2');
108 | var data2 = JSON.parse(entry2);
109 | });
110 |
111 |
--------------------------------------------------------------------------------
/src/iife.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | var temp = 10;
3 | }());
4 |
5 | console.log(temp); // Error, temp is not defined
6 |
7 | // Instead of using IIFE inside of ES5,
8 | // Simply use blocks in ES6
9 | { // open block
10 | let temp = 10;
11 | } // close block
12 |
13 | console.log(temp); // ReferenceError
--------------------------------------------------------------------------------
/src/imports.js:
--------------------------------------------------------------------------------
1 | // main.js
2 | import { sumTwo, sumThree } from 'math/addition';
3 |
4 | // Alternate way to import by providing aliases
5 | import {
6 | sumTwo as addTwoNumbers,
7 | sumThree as addThreeNumbers
8 | } from 'math/addition';
9 |
10 | import * as addition from 'math/addition';
11 |
12 | console.log(sumTwo(2, 3));
13 |
14 | // Alternate calls (1)
15 | console.log(addTwoNumbers(2, 3));
16 |
17 | // Alternate calls (2)
18 | console.log(addition.sumTwo(2, 3));
19 |
20 | ///////////////////////////////////////////////////
21 |
22 | // math/addition.js
23 | function sumTwo(a, b) {
24 | return a + b;
25 | }
26 |
27 | function sumThree(a, b) {
28 | return a + b + c;
29 | }
30 |
31 | export { sumTwo, sumThree };
32 |
33 | // Alternate expoorts
34 |
35 | function sumTwo(a, b) {
36 | return a + b;
37 | }
38 |
39 | function sumThree(a, b) {
40 | return a + b + c;
41 | }
42 |
43 | var api = {
44 | sumTwo : sumTwo,
45 | sumThree: sumThree
46 | }
47 |
48 | export default api
--------------------------------------------------------------------------------
/src/letConst.js:
--------------------------------------------------------------------------------
1 | // ES5
2 |
3 | var snack = 'Meow Mix';
4 |
5 | function getFood(food) {
6 | if (food) {
7 | var snack = 'Friskies';
8 | return snack;
9 | }
10 | return snack;
11 | }
12 |
13 | getFood(false); // Undefined
14 |
15 | // Re-write the above example
16 | var snack = 'Meow Mix';
17 |
18 | function getFood(food) {
19 |
20 | var snack; // Hoisting
21 |
22 | if (food) {
23 | snack = 'Friskies';
24 | return snack;
25 | }
26 |
27 | return snack;
28 | }
29 |
30 | getFood(false); // Undefined
31 |
32 | // ES6
33 |
34 | let snack = 'Meow Mix';
35 |
36 | function getFood(food) {
37 |
38 | if (food) {
39 | let snack = 'Friskies';
40 | return snack;
41 | }
42 |
43 | return snack;
44 | }
45 |
46 | getFood(false);
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Point from './Point.js';
2 | var body = document.querySelector('body');
3 | body.textContent = 'Good point: ' + new Point(1, 23, 99);
--------------------------------------------------------------------------------
/src/maps.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Maps are a new Data Structure in JavaScript.
3 | * They allow us to use arbitrary values as keys.
4 | * Not just strings, as we used hash maps for.
5 | */
6 |
7 | // Hash maps in ES5
8 | var map = new Object();
9 | map[key1] = 'value1';
10 | map[key2] = 'value2';
11 |
12 | // Problem 1
13 | // How do we get our own properties of an object?
14 | function getOwnProperty(object, propertyKey) {
15 | return (object.hasOwnProperty(propertyKey) ? object[propertyKey]: undefined);
16 | }
17 |
18 | // However...what if we overwrite the property hasOwnProperty?
19 | > getOwnProperty({ hasOwnProperty: 'Hah, overwritten'}, 'Pwned');
20 | > TypeError: Propery 'hasOwnProperty' is not a function
21 |
22 | // How to fix?
23 | function getOwnProperty(object, propertyKey) {
24 | return (Object.prototype.hasOwnProperty(object, propertyKey) ? object[propertyKey]: undefined);
25 | }
26 |
27 | // ^ Abuse of an object to create a hash map
28 |
29 | // Actual Maps in ES6
30 | let map = new Map();
31 | > map.set('name', 'david');
32 | > map.get('name'); // david
33 | > map.has('name'); // true
34 |
35 | // Keys in Maps can be more than a string
36 | let map = new Map();
37 |
38 | const KEY = {}; // We can use objects!
39 | > map.set(KEY, 'ES6 for the win');
40 | > map.get((KEY)); // 'ES6 for the win'
41 |
42 | // Iterating over a Map
43 | let map = new Map([
44 | ['name', 'david'],
45 | [true, 'false'],
46 | [1, 'one'],
47 | [{}, 'object'],
48 | [function () {}, 'function']
49 | ]);
50 |
51 | for (let key of map.keys()) {
52 | console.log(typeof key);
53 | // > string, boolean, number, object, function
54 | };
55 |
56 | // .entries()
57 | for (let entry of map.entries()) {
58 | console.log(entry[0], entry[1]);
59 | }
60 |
61 | // More convenient syntax using destructuring:
62 | for (let [key, value] of map.entries()) {
63 | console.log(key, value);
64 | }
65 |
--------------------------------------------------------------------------------
/src/multipleReturnValues.js:
--------------------------------------------------------------------------------
1 | // Object.getOwnPropertyDescriptor returns property descriptors,
2 | // which is an object that holds multiple values in it's properties.
3 |
4 | // When using ES5, note that we still need an intermediate variable
5 | // In this case, it's propDesc
6 | var obj = { bar: '123' };
7 |
8 | var propDesc = Object.getOwnPropertyDescriptor(obj, 'bar');
9 | var writable = propDesc.writable;
10 | var configurable = propDesc.configurable;
11 |
12 | console.log(writable, configurable); // true true
13 |
14 | // Using ES6, we can return multiple values without using intermediate variables
15 | // through the use of destructuring
16 | let obj = { bar: '123' };
17 |
18 | let {writable, configurable} =
19 | Object.getOwnPropertyDescriptor(obj, 'bar');
20 |
21 | console.log(writable, configurable); // true true
22 |
23 | // {writeable, configurable} is equivalent to {writable: writable, configurable: configurable}
24 |
--------------------------------------------------------------------------------
/src/namedParameters.js:
--------------------------------------------------------------------------------
1 | // Example of options object pattern in ES5 for
2 | // handling named parameters
3 | function selectEntries(options) {
4 | var start = options.start || 0;
5 | var end = options.end || -1;
6 | var step = options.step || 1;
7 | }
8 |
9 | // Once again, destructuring to the rescue. We can pass in an object
10 | // as a function parameter in ES6 to handle named parameters.
11 | function selectEntries({ start=0, end=-1, step=1 }) {
12 | // Code here
13 | }
14 |
15 | function initializeCanvas(options) {
16 | var height = options.height || 600;
17 | var width = options.width || 400;
18 | var lineStroke = options.lineStroke || 'black';
19 | }
20 |
21 | function initializeCanvas({ height=600, width=400, lineStroke='black'}) {
22 | ...
23 | }
--------------------------------------------------------------------------------
/src/optionalNamedParameters.js:
--------------------------------------------------------------------------------
1 | // Make parameter options optional in ES5
2 | function selectEntries(options) {
3 | options = options || {}; // optional parameter
4 | var start = options.start || 0;
5 | var end = options.end || -1;
6 | var step = options.step || 1;
7 | }
8 |
9 | // In ES6, we can make the parameter optional by = {}
10 | function selectEntries({ start=0, end=-1, step=1 } = {}) {
11 |
12 | }
--------------------------------------------------------------------------------
/src/promises.js:
--------------------------------------------------------------------------------
1 | /* What are promises?
2 | *
3 | * Promises are basically placeholders for values that will eventually exist.
4 | * They make it easier to reason about code, and are a nice substitute for callbacks.
5 | */
6 |
7 | // Promise allow us to turn our horizontal code:
8 | func1(function (value1) {
9 | func2(value1, function(value2) {
10 | func3(value2, function(value3) {
11 | func4(value3, function(value4) {
12 | func5(value4, function(value5) {
13 | // Do something with value 5
14 | });
15 | });
16 | });
17 | });
18 | });
19 |
20 | // Into...
21 | func1(value1)
22 | .then(func2(value1) { })
23 | .then(func3(value2) { })
24 | .then(func4(value3) { })
25 | .then(func5(value4) {
26 | // Do something with value 5
27 | })
28 |
29 | var data = requests.get('http://swapi.co/api/people/1'); // .get returns a brand new data promises
30 | var response = data.then(res => res.body); // data.then returns another new promise
31 | var save = response.catch(err => console.error(err)); // response.catch returns another new promise
32 |
33 | // requests.get returns a brand new data promise
34 | // data.then returns another new promise
35 | // response.catch returns another new promise
36 | // When data is (fufilled), data.then reaction is executed
37 | // response is then settled who was waiting for data.then to settled
38 | // response was rejected, so we run a .catch instead of .then branch
39 | // save is fufilled and logs the error
40 |
41 | // In ES6, we no longer need libraries to create Promises. We can create them
42 | // from scratch.
43 |
44 | // new Promise(resolve => resolve()) // promise was fufilled
45 | // new Promise((resolve, reject) => reject()) // promise was rejected
46 |
47 | new Promise(resolve => resolve(data))
48 | .then(result => console.log(data));
49 |
50 |
51 | new Promise((resolve, reject) =>
52 | reject(new Error('Failed to fufill Promise')))
53 | .catch(reason => console.log(reason));
54 |
55 |
56 | // Example of a promise
57 | var promise = new Promise(function(resolve, reject) {
58 | if (/* condition */) {
59 | resolve(/* value */); // fulfilled successfully
60 | }
61 | else {
62 | reject(/* reason */); // error, rejected
63 | }
64 | });
65 |
66 | // The first handler (resolve) is called when the Promise has been fufilled,
67 | // and the value has been passed to the handler.
68 |
69 | // The second handler (reject) is called when the Promise has been rejected
70 | // with the value being passed to that handler.
71 |
72 | // A Promise can only be settled (fufilled/rejected) once, and this value is immutable.
73 |
74 | // Talk about concurrent promises using Promises.all
75 |
76 | // Promises in summary:
77 | // * Promises allow us to write asynchronous code in a synchronous matter
78 | // * Promises allow us to unify asynchronous APIS
79 | // * Promises guarantees no race conditions and immutability of the future value
80 | // represented by the promise
81 |
82 | // Promise example using getJson, to highlight multiple promises
83 | var fetchJSON = function(url) {
84 | return new Promise((resolve, reject) => {
85 | $.getJSON(url)
86 | .done((json) => resolve(json))
87 | .fail((xhr, status, err) => reject(status + err.message));
88 | });
89 | }
90 |
91 | var urls = {
92 | 'http://www.api.com/items/1234',
93 | 'http://www.api.com/items/4567'
94 | };
95 |
96 | var urlPromises = urls.map(fetchJSON);
97 |
98 | Promise.all(urlPromises)
99 | .then(function(results) {
100 | // If all the promises are fufilled,
101 | // we now execute this
102 | results.forEach(function(data) {
103 | // process our data
104 | });
105 | })
106 | .catch(function(err) {
107 | // Will catch failure of first failed promise
108 | console.log("Failed:", err);
109 | });
110 |
111 |
--------------------------------------------------------------------------------
/src/sets.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Sets are a new data structure in ES6.
3 | * Contains unique elements, is faster and handles NaN
4 | * The reason for this is that storing arbitrary
5 | * elements in an array (ES5) means we need to write
6 | * filter methods. Also, indexOf cannot handle NaN.
7 | */
8 |
9 | let set = new Set();
10 | > set.add('javascript');
11 | > set.has('javascript'); // true
12 | > set.delete('javascript');
13 | > set.has('javascript'); // false
14 |
15 | // Mapping a set
16 | let set = new Set([1, 2, 3, 4, 5]);
17 | set = new Set([...set].map(val => val * 2));
18 | console.log(set); // {2, 4, 6, 8, 10}
19 |
20 | // Filtering a set
21 | let set = new Set([1, 2, 3, 4, 5]);
22 | set = new Set([...set].filter(val => val % 2));
23 | console.log(set); // {2, 4}
--------------------------------------------------------------------------------
/src/spread.js:
--------------------------------------------------------------------------------
1 | // Concatenating an array of strings using ES5
2 | function concat () {
3 | return Array.prototype.slice.call(arguments).join(' ')
4 | }
5 |
6 | var result = concat('The', 'cat', 'went', 'meow');
7 | console.log(result); // 'The cat went meow'
8 |
9 | // Concatenating an array of strings using ES6
10 | function concat(...params) {
11 | return params.join(' ');
12 | }
13 |
14 | var result = concat('The', 'cat', 'went', 'meow');
15 | console.log(result); // 'The cat went meow'
16 |
17 | const phrasesOne = ['The', 'cat'];
18 | const phrasesTwo = ['went', 'meow'];
19 |
20 | phrasesOne.push(...phrasesTwo);
21 | // phrasesOne = ['The', 'cat', 'went', 'meow']
22 |
--------------------------------------------------------------------------------
/src/stringInterpolation.js:
--------------------------------------------------------------------------------
1 | // String Interpolation in ES5
2 | function printCoord(x, y) {
3 | console.log('('+x+', '+y+')');
4 | }
5 |
6 | // String interperation in ES6 using template literals
7 | function printCoord(x, y) {
8 | console.log(`(${x}, ${y})`);
9 | }
--------------------------------------------------------------------------------
/src/strings.js:
--------------------------------------------------------------------------------
1 | // ES5
2 |
3 | var string = 'food';
4 |
5 | var substring = 'foo';
6 |
7 | // Check if substring is contained in string
8 | console.log(string.indexOf(substring) > -1);
9 |
10 | // ES6
11 |
12 | const string = 'food';
13 |
14 | const substring = 'foo';
15 |
16 | // Check if substring is contained in string
17 | console.log(string.includes(substring)); // true
18 |
19 |
--------------------------------------------------------------------------------
/src/sumOfSquares.js:
--------------------------------------------------------------------------------
1 | // Return sum of squares of arr
2 | var arr = [1, 2, 3];
3 | var squares = arr.map(function (x) {
4 | return x * x
5 | });
6 |
7 | // Using the arrow function, we have a more concise solution.
8 | // Arrow functions are extremely useful to replace callbacks
9 | // which simply return the result of an expression.
10 | let arr = [1, 2, 3];
11 | let squares = arr.map(x => x * x);
--------------------------------------------------------------------------------
/src/symbols.js:
--------------------------------------------------------------------------------
1 | /* Symbols are a new primitive type useful for:
2 | * 1. Unique Property Keys
3 | * 2. Constants that represent a concept
4 | */
5 |
6 | // Symbols used as Property Keys
7 | const key = Symbol();
8 | const keyTwo = Symbol();
9 | const object = {};
10 |
11 | object.key = 'Such magic.';
12 | object.keyTwo = 'Much Uniqueness'
13 | console.log(object.key);
14 | console.log(object.keyTwo);
15 |
16 | // Symbols are always Unique
17 | console.log(key === keyTwo);
18 |
19 | // Symbols are good for representing concepts
20 | const anakin = 'jedi';
21 | const yoda = 'jedi master';
22 | const luke = 'jedi';
23 |
24 | // Now the value of 'jedi' is not Unique. Fix this with Symbols
25 | const anakin = Symbol();
26 | const yoda = Symbol();
27 | const luke = Symbol();
28 |
29 | // Now values cannot be confused
30 | // Symbols are similar to strings, as they can represent
31 | // concepts and properties. On the other hand, they also
32 | // exhibit functionality of an object, as each symbol has
33 | // its own identity.
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 |
3 | module.exports = {
4 | entry: './src/main.js',
5 | output: {
6 | path: __dirname,
7 | filename: 'bundle.js'
8 | },
9 | module: {
10 | loaders: [
11 | {
12 | test: /\.js/,
13 | loader: 'babel-loader',
14 | query: {
15 | presets: ['es2015']
16 | }
17 | }
18 | ]
19 | }
20 | };
--------------------------------------------------------------------------------