├── .gitignore ├── Dockerfile ├── presentation.pdf ├── autostart.sh ├── README.md ├── test ├── 02-const-test.js ├── 03-function-in-block-test.js ├── 06-generator-test.js ├── 08-class-test.js ├── 07-promise-test.js ├── 01-let-test.js ├── 05-set-test.js └── 04-map-test.js ├── package.json └── presentation.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | 3 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM iojs:onbuild 2 | CMD [ "npm", "test" ] 3 | 4 | -------------------------------------------------------------------------------- /presentation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subfuzion/demo-iojs-es6/HEAD/presentation.pdf -------------------------------------------------------------------------------- /autostart.sh: -------------------------------------------------------------------------------- 1 | wget https://iojs.org/dist/v1.6.2/iojs-v1.6.2-linux-x64.tar.gz 2 | tar zxf iojs-v1.6.2-linux-x64.tar.gz 3 | cd iojs-v1.6.2-linux-x64 4 | rm /usr/bin/node 5 | rm /usr/bin/npm 6 | ln -s /workspace/iojs-v1.6.2-linux-x64/bin/node /usr/bin/node 7 | ln -s /workspace/iojs-v1.6.2-linux-x64/bin/npm /usr/bin/npm 8 | ln -s /workspace/iojs-v1.6.2-linux-x64/bin/iojs /usr/bin/iojs 9 | 10 | npm install 11 | npm test 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | io.js Ecmascript 6 language features 2 | ==================================== 3 | 4 | npm install 5 | npm test 6 | 7 | You can also run individual tests: 8 | 9 | npm run test-let 10 | npm run test-const 11 | npm run test-function-in-blocks 12 | npm run test-map 13 | npm run test-set 14 | npm run test-generator 15 | npm run test-promise 16 | npm run test-class 17 | 18 | You can view the presentation as [markdown](https://github.com/tonypujals/demo-iojs-es6/blob/master/presentation.md) or a [pdf](https://github.com/tonypujals/demo-iojs-es6/raw/master/presentation.pdf). 19 | 20 | If you would like to use promises with existing Node modules (fs, http, etc), you might want to try [@atomiq/promisify](https://github.com/atomiqio/promisify) 21 | 22 | 23 | -------------------------------------------------------------------------------- /test/02-const-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const assert = require('assert'); 3 | 4 | describe ('const', function() { 5 | 6 | it ('cannot redeclare a const', function() { 7 | 8 | const a = 5; 9 | 10 | // throws SyntaxError: 11 | // const a = 10; 12 | 13 | }); 14 | 15 | it ('cannot reassign a const', function() { 16 | 17 | const a = 5; 18 | 19 | assert.throws(function() { 20 | // throws TypeError 21 | a = 10; 22 | 23 | }); 24 | 25 | }); 26 | 27 | it ('const requires an initial value', function() { 28 | 29 | // throws SyntaxError: 30 | // const a; 31 | 32 | }); 33 | 34 | it ('remember, const object properties aren\'t protected', function() { 35 | 36 | const o = { name: 'silly' }; 37 | 38 | o.name = 'sally'; 39 | 40 | assert.equal(o.name, 'sally'); 41 | 42 | }); 43 | 44 | }); 45 | 46 | -------------------------------------------------------------------------------- /test/03-function-in-block-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const assert = require('assert'); 3 | 4 | describe('function-in-blocks', function () { 5 | it ('this always worked (function in function)', function() { 6 | 7 | function greet() { 8 | 9 | function foo() { 10 | 11 | function greet() { 12 | return 'meow'; 13 | } 14 | 15 | assert.equal(greet(), 'meow'); 16 | } 17 | 18 | return 'woof'; 19 | } 20 | 21 | // => woof in test scope 22 | assert.equal(greet(), 'woof'); 23 | 24 | }); 25 | 26 | it ('greet function declared in two different scopes (function in block)', function() { 27 | 28 | function greet() { 29 | return 'woof'; 30 | } 31 | 32 | if (true) { 33 | // function defined inside block 34 | function greet() { 35 | return 'meow'; 36 | } 37 | 38 | assert.equal(greet(), 'meow'); 39 | } 40 | 41 | assert.equal(greet(), 'woof'); 42 | 43 | }); 44 | 45 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "let-demo", 3 | "version": "1.0.0", 4 | "description": "", 5 | "scripts": { 6 | "test": "mocha -- --harmony_arrow_functions", 7 | "test-let": "mocha --grep let -- --harmony_arrow_functions", 8 | "test-const": "mocha --grep const -- --harmony_arrow_functions", 9 | "test-function-in-blocks": "mocha --grep function-in-blocks -- --harmony_arrow_functions", 10 | "test-map": "mocha --grep map -- --harmony_arrow_functions", 11 | "test-set": "mocha --grep set -- --harmony_arrow_functions", 12 | "test-generator": "mocha --grep generator -- --harmony_arrow_functions", 13 | "test-promise": "mocha --grep promise -- --harmony_arrow_functions", 14 | "test-class": "mocha --grep class -- --harmony_arrow_functions" 15 | }, 16 | "author": "Tony Pujals (http://twitter.com/subfuzion)", 17 | "license": "ISC", 18 | "devDependencies": { 19 | "chai": "^2.2.0", 20 | "mocha": "^2.2.1" 21 | }, 22 | "engines": { 23 | "iojs": "^2.0.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test/06-generator-test.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | const assert = require('assert'); 3 | 4 | describe('generator', function() { 5 | 6 | it ('should generate consecutive numbers from 0-2', function() { 7 | 8 | function* numgenerator() { 9 | for (let i = 0; i < 3; i++) { 10 | yield i; 11 | } 12 | } 13 | 14 | let g = numgenerator(); 15 | 16 | assert.equal(g.next().value, 0); 17 | assert.equal(g.next().value, 1); 18 | assert.equal(g.next().value, 2); 19 | 20 | // return object conforms to iterator protocol (has done and value properties) 21 | let next = g.next(); 22 | assert(next.done); 23 | assert.equal(next.value, undefined); 24 | 25 | }); 26 | 27 | it ('should catch exception when calling next the second time', function() { 28 | 29 | function* errorGenerator() { 30 | yield 1; 31 | throw new Error(); 32 | } 33 | 34 | let g = errorGenerator(); 35 | 36 | assert.equal(g.next().value, 1); 37 | 38 | assert.throws(function() { 39 | g.next(); 40 | }); 41 | 42 | }); 43 | 44 | }); 45 | -------------------------------------------------------------------------------- /test/08-class-test.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | const assert = require('assert'); 3 | const util = require('util'); 4 | 5 | describe ('class', function() { 6 | 7 | class Animal { 8 | 9 | constructor(name, noise) { 10 | this._name = name; 11 | this.noise = noise; 12 | Animal.incrementCount(); 13 | } 14 | 15 | set name(name) { 16 | this._name = name; 17 | } 18 | 19 | get name() { 20 | return this._name; 21 | } 22 | 23 | makeNoise() { 24 | return util.format('%s says %s', this.name, this.noise); 25 | } 26 | 27 | static incrementCount() { 28 | // this is the prototype for Animal, so count is 29 | // shared for all instances 30 | if (!this.count) this.count = 0; 31 | this.count++; 32 | } 33 | 34 | static getCount() { 35 | return this.count || 0; 36 | } 37 | 38 | } 39 | 40 | class Dog extends Animal { 41 | constructor(name) { 42 | super(name, 'woof'); 43 | } 44 | } 45 | 46 | class Cat extends Animal { 47 | constructor(name) { 48 | super(name, 'meow'); 49 | } 50 | } 51 | 52 | it ('dog should say woof', function() { 53 | let dog = new Dog('fido'); 54 | assert.equal( dog.name, 'fido' ); 55 | assert.equal( dog.noise, 'woof' ); 56 | assert.equal( dog.makeNoise(), 'fido says woof'); 57 | }); 58 | 59 | it ('cat should say meow', function() { 60 | let cat = new Cat('sylvester'); 61 | assert.equal( cat.name, 'sylvester' ); 62 | assert.equal( cat.noise, 'meow' ); 63 | assert.equal( cat.makeNoise(), 'sylvester says meow'); 64 | }); 65 | 66 | it ('should keep track of animal count', function() { 67 | assert.equal( Animal.getCount(), 2 ); 68 | }); 69 | 70 | }); -------------------------------------------------------------------------------- /test/07-promise-test.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | const assert = require('assert'); 3 | 4 | describe('promise', function () { 5 | // increase mocha default timeout (2 sec) so tests can run 6 | this.timeout(5000); 7 | 8 | // standard idiomatic node async function that expects a callback 9 | // this example expects a timeout value in milliseconds; the function 10 | // will callback with the string 'success' unless the timeout value 11 | // exceeded 3000 ms, in which case it will callback with an error after 12 | // 3000 ms 13 | function asyncFunc(timeout, callback) { 14 | let limit = Math.min(timeout, 3000); 15 | 16 | setTimeout(function () { 17 | 18 | if (limit < timeout) { 19 | return callback(new Error('timed out')); 20 | } 21 | 22 | callback(null, 'success'); 23 | 24 | }, limit); 25 | } 26 | 27 | // promisified version of asyncFunc 28 | function promiseFunc(timeout) { 29 | 30 | return new Promise(function (resolve, reject) { 31 | 32 | asyncFunc(timeout, function (err, result) { 33 | 34 | return err ? reject(err) : resolve(result); 35 | 36 | }); 37 | 38 | }); 39 | } 40 | 41 | it('should succeed after 2 seconds', function (done) { 42 | 43 | promiseFunc(2000) 44 | .then(function (result) { 45 | 46 | assert.equal(result, 'success'); 47 | done(); 48 | 49 | }) 50 | .catch(function (err) { 51 | done(err); 52 | }); 53 | 54 | }); 55 | 56 | it('should fail after 3 seconds', function (done) { 57 | 58 | promiseFunc(9000) 59 | .then(function (result) { 60 | done(new Error('should not have succeeded')); 61 | }) 62 | .catch(function (err) { 63 | 64 | done(); 65 | }); 66 | 67 | }); 68 | 69 | // this example also demonstrates arrow functions ("fat arrow") 70 | it('should chain consecutive then actions', function (done) { 71 | let counter = 0; 72 | 73 | promiseFunc(1000) 74 | .then((result) => { 75 | 76 | counter++; 77 | assert.equal(result, 'success'); 78 | return promiseFunc(1000); 79 | 80 | }).then((result) => { 81 | 82 | counter++; 83 | assert.equal(counter, 2); 84 | assert.equal(result, 'success'); 85 | done(); 86 | 87 | }); 88 | 89 | }); 90 | 91 | }); 92 | 93 | -------------------------------------------------------------------------------- /test/01-let-test.js: -------------------------------------------------------------------------------- 1 | // strict mode is required for block-scoped declarations (let, const, function, class) 2 | // or a SyntaxError will be thrown 3 | "use strict" 4 | const assert = require('assert'); 5 | 6 | describe('let', function() { 7 | 8 | describe('var hoisting and redeclaration examples for comparison to let', function () { 9 | 10 | // http://www.sitepoint.com/demystifying-javascript-variable-scope-hoisting/ 11 | // http://code.tutsplus.com/tutorials/javascript-hoisting-explained--net-15092 12 | 13 | it('should throw a ReferenceError because `b` is never declared', function () { 14 | try { 15 | var a = b; 16 | } catch (err) { 17 | assert(err instanceof ReferenceError); 18 | } 19 | }); 20 | 21 | it('should demonstrate var declaration hoisting', function () { 22 | // no error is thrown since b is declared in the function... 23 | // ...it's declaration is effectively "hoisted" to the top of the function 24 | // With hoisting, it's as if the code looked like this: 25 | // var a; 26 | // var b; 27 | // 28 | // a = b; // a is undefined since b is undefined 29 | // b = 'hello'; 30 | 31 | 32 | var a = b; 33 | var b = 'hello'; 34 | 35 | // Note: although the *declaration* of b was hoisted, it's *value* 36 | // wasn't set until the line after the assignment to a 37 | // ==> b's value was undefined, therefore a is undefined 38 | assert(a === undefined); 39 | }); 40 | 41 | it('redeclaration of var is still same variable', function () { 42 | var a = 3; 43 | 44 | if (true) { 45 | var a = 2; // same variable 46 | assert.equal(a, 2); 47 | } 48 | 49 | assert.equal(a, 2); // still same variable 50 | 51 | }); 52 | 53 | }); 54 | 55 | 56 | describe('let examples', function () { 57 | 58 | it('let does not hoist, so should throw a ReferenceError', function () { 59 | 60 | try { 61 | let a = b; // b is not declared and won't be hoisted, so this will fail 62 | let b = 'hello'; 63 | } catch (err) { 64 | assert(err instanceof ReferenceError); 65 | } 66 | 67 | }); 68 | 69 | it('let block scope', function () { 70 | 71 | let a = 3; 72 | let b = 2; 73 | 74 | if (true) { 75 | let a = 10; 76 | b = 20; 77 | } 78 | 79 | assert.equal(a, 3); 80 | assert.equal(b, 20); 81 | 82 | }); 83 | 84 | it('let-scoped variables in for loops', function () { 85 | let i = 10; 86 | let counter = 0; 87 | 88 | // i scoped to for block 89 | for (let i = 0; i < 3; i++, counter++) { 90 | } 91 | 92 | assert.equal(counter, 3); 93 | assert.equal(i, 10); 94 | 95 | }); 96 | 97 | it('careful with switch statements', function () { 98 | 99 | let a = 0; 100 | 101 | switch (a) { 102 | // the following case would fail (missing curly braces for block) 103 | // (=> SyntaxError: Illegal let declaration in unprotected statement context) 104 | // 105 | // case 0: 106 | // let b; 107 | // break; 108 | 109 | // explicit block is required: 110 | 111 | case 1: 112 | { 113 | let b; 114 | break; 115 | } 116 | } 117 | 118 | }); 119 | 120 | }); 121 | 122 | }); 123 | 124 | -------------------------------------------------------------------------------- /test/05-set-test.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | const assert = require('assert'); 3 | 4 | describe ('set', function() { 5 | 6 | it ('sets can store any type including NaN', function() { 7 | 8 | let set = new Set( [1, 2] ); 9 | 10 | assert.equal( set.size, 2 ); 11 | assert( set.has(1) ); 12 | assert( set.has(2) ); 13 | 14 | set.add(3); 15 | set.add(3); // doesn't throw 16 | assert.equal( set.size, 3 ); 17 | 18 | assert( set.has(3) ); 19 | assert( !set.has(4) ); 20 | 21 | set.delete(3); 22 | assert( !set.has(3) ); 23 | assert.equal( set.size, 2 ); 24 | 25 | set.add(NaN); 26 | assert( set.has(NaN) ); 27 | assert.equal( set.size, 3 ); 28 | 29 | set.add(Number('definitely not a number')); 30 | // set is still the same size 31 | assert.equal( set.size, 3 ); 32 | 33 | }); 34 | 35 | }); 36 | 37 | describe ('set iteration examples', function() { 38 | 39 | let set = new Set( [ 'A', 'B' ] ); 40 | 41 | it ('set size', function() { 42 | 43 | // the size of a set is the number of elements it has 44 | assert.equal(set.size, 2); 45 | 46 | }); 47 | 48 | it ('set values iteration by forEach', function() { 49 | let values = []; 50 | 51 | // set.values().forEach 52 | set.forEach(function(value) { 53 | values.push(value); 54 | }); 55 | 56 | assert.equal( values[0], 'A' ); 57 | assert.equal( values[1], 'B' ); 58 | 59 | }); 60 | 61 | it ('set iteration', function() { 62 | let values = []; 63 | 64 | // iterate a set by key/value pairs (a pair is an array with 2 elements for the key and value) 65 | // arrays enumerate in the same order that set entries were added 66 | for (let item of set) { 67 | values.push(item); 68 | } 69 | 70 | assert.equal( values[0], 'A' ); 71 | assert.equal( values[1], 'B' ); 72 | 73 | }); 74 | 75 | it ('set iteration by entries', function() { 76 | let entries = set.entries(); 77 | 78 | let entry = entries.next(); 79 | assert.equal( entry.done, false ); 80 | assert.equal( entry.value[0], 'A' ); 81 | assert.equal( entry.value[1], 'A' ); 82 | 83 | entry = entries.next(); 84 | assert.equal( entry.done, false ); 85 | assert.equal( entry.value[0], 'B' ); 86 | assert.equal( entry.value[1], 'B' ); 87 | }); 88 | 89 | it ('set iteration by keys', function() { 90 | 91 | let keys = set.keys(); 92 | 93 | let next = keys.next(); 94 | assert.equal( next.value, 'A' ); 95 | assert.equal( next.done, false ); 96 | 97 | next = keys.next(); 98 | assert.equal( next.value, 'B' ); 99 | assert.equal( next.done, false ); 100 | 101 | next = keys.next(); 102 | assert.equal( next.value, undefined ); 103 | assert.equal( next.done, true ); 104 | 105 | }); 106 | 107 | it ('set iteration by values', function() { 108 | 109 | let values = set.values(); 110 | 111 | let next = values.next(); 112 | assert.equal( next.value, 'A' ); 113 | assert.equal( next.done, false ); 114 | 115 | next = values.next(); 116 | assert.equal( next.value, 'B' ); 117 | assert.equal( next.done, false ); 118 | 119 | next = values.next(); 120 | assert.equal( next.value, undefined ); 121 | assert.equal( next.done, true ); 122 | 123 | }); 124 | 125 | it ('more set functions', function() { 126 | 127 | // set contains value='0' 128 | assert( set.has('A') ); 129 | 130 | // delete the element where value='0' 131 | assert( set.delete('A') ); 132 | 133 | // only 1 entry left 134 | assert(set.size, 1); 135 | 136 | set.clear(); 137 | assert.equal(set.size, 0); 138 | 139 | }); 140 | }); -------------------------------------------------------------------------------- /test/04-map-test.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | const assert = require('assert'); 3 | 4 | describe ('map', function() { 5 | 6 | it ('maps can use types other than strings for keys', function() { 7 | 8 | let map = new Map(); 9 | 10 | let s = ''; 11 | let i = 0; 12 | let obj = {}; 13 | let func = function() {}; 14 | 15 | map.set(s, 'key is a string'); 16 | map.set(i, 'key is a number'); 17 | map.set(obj, 'key is an object'); 18 | map.set(func, 'key is a function'); 19 | 20 | assert.equal(map.get(s), 'key is a string'); 21 | assert.equal(map.get(i), 'key is a number'); 22 | assert.equal(map.get(obj), 'key is an object'); 23 | assert.equal(map.get(func), 'key is a function'); 24 | 25 | }); 26 | 27 | it ('two object references', function() { 28 | 29 | let a = {}; 30 | let b = {}; 31 | let map = new Map(); 32 | 33 | map.set(a, 'obj1'); 34 | map.set(b, 'obj2'); 35 | 36 | assert(map.get(a) != map.get(b)); 37 | 38 | }); 39 | 40 | it ('maps work with NaN also', function() { 41 | 42 | let map = new Map(); 43 | 44 | map.set(NaN, 'key is not a number'); 45 | 46 | let nan = Number('definitely not a number'); 47 | 48 | // even though NaN !== NaN, this still works because the keys are indistinguishable 49 | assert.equal(map.get(nan), 'key is not a number'); 50 | 51 | // (just to prove NaN !== NaN) 52 | assert(NaN !== NaN); 53 | 54 | }); 55 | 56 | 57 | }); 58 | 59 | describe ('map iteration examples', function() { 60 | 61 | let map = new Map(); 62 | 63 | for (let i = 0; i < 2; i++) { 64 | map.set(i, String(i)); 65 | } 66 | 67 | it ('map size', function() { 68 | 69 | // the size of a map is the number of key/value pairs it has 70 | assert.equal(map.size, 2); 71 | 72 | }); 73 | 74 | it ('map values iteration by forEach', function() { 75 | let values = []; 76 | 77 | // map.values().forEach 78 | map.forEach(function(value) { 79 | values.push(value); 80 | }); 81 | 82 | for (let i = 0; i < map.size; i++) { 83 | assert.equal(values[i], map.get(i)); 84 | } 85 | 86 | }); 87 | 88 | it ('map iteration using for-of loop', function() { 89 | let pairs = []; 90 | 91 | // iterate a map by key/value pairs (a pair is an array with 2 elements for the key and value) 92 | // arrays enumerate in the same order that map entries were added 93 | // should look like this when done: 94 | // [ 95 | // [ 0, '0' ], 96 | // [ 1, '1' ] 97 | // ] 98 | for (let pair of map) { 99 | pairs.push(pair); 100 | } 101 | 102 | let first = pairs[0]; 103 | assert.equal(first[0], 0); 104 | assert.equal(first[1], '0'); 105 | 106 | let second = pairs[1]; 107 | assert.equal(second[0], 1); 108 | assert.equal(second[1], '1'); 109 | 110 | }); 111 | 112 | it ('map iteration by entries', function() { 113 | let entries = map.entries(); 114 | 115 | let entry = entries.next(); 116 | assert.equal( entry.done, false ); 117 | assert.equal( entry.value[0], 0 ); 118 | assert.equal( entry.value[1], '0' ); 119 | 120 | entry = entries.next(); 121 | assert.equal( entry.done, false ); 122 | assert.equal( entry.value[0], 1 ); 123 | assert.equal( entry.value[1], '1' ); 124 | }); 125 | 126 | it ('map iteration by keys', function() { 127 | 128 | let keys = map.keys(); 129 | 130 | let next = keys.next(); 131 | assert.equal( next.value, 0 ); 132 | assert.equal( next.done, false ); 133 | 134 | next = keys.next(); 135 | assert.equal( next.value, 1 ); 136 | assert.equal( next.done, false ); 137 | 138 | next = keys.next(); 139 | assert.equal( next.value, undefined ); 140 | assert.equal( next.done, true ); 141 | 142 | }); 143 | 144 | it ('map iteration by keys', function() { 145 | 146 | let counter = 0; 147 | 148 | for (let key of map.keys()) { 149 | assert.equal(key, counter); 150 | counter++; 151 | } 152 | 153 | }); 154 | 155 | it ('map iteration by values', function() { 156 | 157 | let values = map.values(); 158 | 159 | let next = values.next(); 160 | assert.equal( next.value, '0' ); 161 | assert.equal( next.done, false ); 162 | 163 | next = values.next(); 164 | assert.equal( next.value, '1' ); 165 | assert.equal( next.done, false ); 166 | 167 | next = values.next(); 168 | assert.equal( next.value, undefined ); 169 | assert.equal( next.done, true ); 170 | 171 | }); 172 | 173 | it ('more map functions', function() { 174 | 175 | // map has entry with key=0 176 | assert( map.has(0) ); 177 | 178 | // delete the entry for key=0 179 | assert( map.delete(0) ); 180 | assert( !map.has(0) ); 181 | 182 | // only 1 entry left 183 | assert.equal(map.size, 1); 184 | 185 | map.clear(); 186 | assert.equal(map.size, 0); 187 | 188 | }); 189 | }); -------------------------------------------------------------------------------- /presentation.md: -------------------------------------------------------------------------------- 1 | # io.js 2 | ## ES6 Features 3 | 4 | ![](http://roadmap.iojs.org/pictures/cover.jpg) 5 | 6 | --- 7 | 8 | ## io.js 2.1.0 9 | 10 | --- 11 | 12 | ## Switching between 13 | ## Node.js & io.js versions 14 | 15 | --- 16 | 17 | ### nvm (node version manager) 18 | 19 | `nvm` makes it easy to switch between versions 20 | 21 | [https://github.com/creationix/nvm](https://github.com/creationix/nvm) 22 | 23 | ```sh 24 | nvm install iojs 25 | 26 | Switching: 27 | nvm use iojs 28 | nvm use node 29 | ``` 30 | 31 | --- 32 | 33 | ### nvm bash completion 34 | 35 | * Add to your `.bash_profile` or `.bashrc` file 36 | 37 | ```sh 38 | [ -r $NVM_DIR/bash_completion ] && . $NVM_DIR/bash_completion 39 | ``` 40 | 41 | ### Example 42 | 43 | $ nvm [tab][tab] 44 | alias deactivate install ls run unload 45 | clear-cache exec list ls-remote unalias use 46 | current help list-remote reinstall-packages uninstall version 47 | 48 | --- 49 | 50 | ## ES6 features available by default 51 | 52 | --- 53 | 54 | * No runtime flag required 55 | * But make sure to add `"use strict"` to top of module 56 | 57 | ### The rest of this presentation goes with the test code here: 58 | [https://github.com/tonypujals/demo-iojs-es6/](https://github.com/tonypujals/demo-iojs-es6/) 59 | 60 | --- 61 | 62 | ## block scoping features 63 | 64 | --- 65 | 66 | ## let 67 | 68 | Get used to it. Use it instead of var. 69 | 70 | * declares a block scope local variable 71 | * optionally initialized to a value 72 | * eliminates weirdness due to var hoisting 73 | 74 | ```js 75 | let var1 = value1; 76 | ``` 77 | 78 | --- 79 | 80 | ## const 81 | 82 | * creates a read-only named constant 83 | 84 | ```js 85 | const name1 = value1 86 | ``` 87 | 88 | --- 89 | 90 | ## Function in blocks 91 | 92 | Could always create a function inside of a function scope 93 | Now can create a function inside of block scope as well 94 | 95 | --- 96 | 97 | ```js 98 | it ('greet function declared in two different scopes (function in block)', function() { 99 | 100 | function greet() { 101 | return 'woof'; 102 | } 103 | 104 | if (true) { 105 | // function defined inside block 106 | function greet() { 107 | return 'meow'; 108 | } 109 | 110 | assert.equal(greet(), 'meow'); 111 | } 112 | 113 | assert.equal(greet(), 'woof'); 114 | 115 | }); 116 | ``` 117 | 118 | --- 119 | 120 | ## Collections 121 | 122 | --- 123 | 124 | * Map 125 | * WeakMap 126 | * Set 127 | * WeakSet 128 | 129 | --- 130 | 131 | ## Map 132 | 133 | * simple key/value map, iterates in order entries were added 134 | * keys can be any object, not just string 135 | * advantages of map over object 136 | * object has a prototype with default keys 137 | * object keys must be strings 138 | * can easily get the size of a map 139 | 140 | #### [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) 141 | 142 | --- 143 | 144 | ### Common Functions 145 | 146 | * get(key) / set(key, value) 147 | * has(key) 148 | * keys(), values() 149 | * delete(key), clear() 150 | 151 | ### Common Properties 152 | 153 | * size 154 | 155 | --- 156 | 157 | ### Iteration 158 | 159 | ```js 160 | let map = new Map(); 161 | ``` 162 | 163 | * by values 164 | 165 | ```js 166 | map.forEach(function(value) { 167 | ... 168 | }); 169 | ``` 170 | * by key-value pairs 171 | 172 | ```js 173 | for (let pair of map) { 174 | // pair is an array [ key, value ] 175 | } 176 | ``` 177 | 178 | --- 179 | 180 | ### map iteration continued 181 | 182 | * by a pair iterator 183 | 184 | ```js 185 | let entries = map.entries(); 186 | let entry = entries.next(); 187 | // entry.done 188 | // entry.value[0] => key 189 | // entry.value[1] => value 190 | 191 | ``` 192 | 193 | --- 194 | 195 | ### map iteration continued 196 | 197 | ```js 198 | let keys = map.keys(); 199 | let next = keys.next(); 200 | // next.value 201 | // next.done 202 | ``` 203 | or using `for-of` loop 204 | 205 | ```js 206 | for (let key of map.keys()) { 207 | } 208 | ``` 209 | 210 | --- 211 | 212 | ### map iteration continued 213 | 214 | ```js 215 | let values = map.values(); 216 | let next = values.next(); 217 | // next.value 218 | // next.done 219 | ``` 220 | 221 | or using `for-of` loop 222 | 223 | ```js 224 | for (let value of map.values()) { 225 | } 226 | ``` 227 | 228 | --- 229 | 230 | ## WeakMap 231 | 232 | Use when you don't want to prevent garbage collection when there are no other references to an object other than the key. 233 | 234 | * collection of key/value pairs 235 | * keys must be objects 236 | * keys are not enumerable 237 | 238 | #### [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap) 239 | 240 | --- 241 | 242 | ## Set 243 | 244 | A collection of unique values of any type. 245 | 246 | * can store `undefined` 247 | * can store `NaA` (will only store one instance even though `NaN !== NaN`) 248 | * iterates in insertion order 249 | 250 | #### [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) 251 | 252 | --- 253 | 254 | ### Common Functions 255 | 256 | * add(value) 257 | * has(key) 258 | * values(), keys() 259 | * delete(key), clear() 260 | 261 | ### Common Properties 262 | 263 | * size 264 | 265 | --- 266 | 267 | ## WeakSet 268 | 269 | A collection of weakly held objects 270 | 271 | * elements must be objects 272 | * elements are not enumerable 273 | 274 | #### [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet) 275 | 276 | --- 277 | 278 | ## Generators 279 | 280 | --- 281 | 282 | **`function*`** defines a generator function, which returns a Generator object. 283 | 284 | * simplifies iteration using `yield` to return a value (or throw an error) back to caller 285 | 286 | ```js 287 | function* name([param[, param[, ... param]]]) { 288 | statements 289 | } 290 | ``` 291 | --- 292 | 293 | ```js 294 | function* gen() { 295 | yield 1; 296 | yield 2; 297 | yield 3; 298 | } 299 | 300 | var g = gen(); // "Generator { }" 301 | ``` 302 | 303 | #### [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator) 304 | 305 | --- 306 | 307 | ## Promises 308 | 309 | --- 310 | 311 | ## Promise 312 | 313 | * a promise represents a pending value that will be provided in the future 314 | * a pending promise becomes *settled* when it is *fulfilled* (succeeds) with a value or *rejected* (fails) with a reason 315 | * alternative to using callbacks for asynchronous programming 316 | 317 | --- 318 | 319 | ## Promisify function that expects a callback 320 | 321 | Wrap function in another function that returns a Promise 322 | 323 | --- 324 | 325 | ```js 326 | function promiseFunc(arg) { 327 | 328 | return new Promise(function (resolve, reject) { 329 | 330 | asyncFunc(arg, function (err, result) { 331 | 332 | return err ? reject(err) : resolve(result); 333 | 334 | }); 335 | 336 | }); 337 | } 338 | ``` 339 | 340 | --- 341 | 342 | ## Calling promisified function 343 | 344 | Provide `then` and `catch` handlers 345 | Can chain `then` handlers 346 | 347 | --- 348 | 349 | ```js 350 | promiseFunc(arg) 351 | .then(function (result) { 352 | ... 353 | }) 354 | .catch(function (err) { 355 | ... 356 | }); 357 | ``` 358 | 359 | --- 360 | 361 | ## Same thing but with "fat" arrow functions 362 | 363 | ```js 364 | promiseFunc(arg) 365 | .then((result) => { 366 | ... 367 | }) 368 | .catch((err) => { 369 | ... 370 | }); 371 | ``` 372 | 373 | --- 374 | 375 | ## Classes 376 | 377 | --- 378 | 379 | ### Classes 380 | 381 | * syntactic sugar over prototype-based OOP model 382 | * inheritance 383 | * constructor 384 | * super 385 | * static 386 | * get / set methods 387 | 388 | 389 | --- 390 | 391 | ## ES6 features that still need flags 392 | 393 | --- 394 | 395 | ## "Fat" arrow functions 396 | 397 | --- 398 | 399 | ## Arrow functions 400 | 401 | Finally ... **`this`** works! 402 | 403 | Need to pass the **`__harmony_arrow_function`** option 404 | 405 | ```sh 406 | iojs --harmony_arrow_functions index.js 407 | ``` 408 | 409 | or 410 | 411 | ``` 412 | mocha -- --harmony_arrow_functions 413 | ``` 414 | 415 | --- 416 | 417 | ### Compare 418 | 419 | ```js 420 | function Person(){ 421 | this.age = 0; 422 | 423 | setInterval(function() { 424 | this.age++; 425 | }.bind(this), 1000); 426 | } 427 | 428 | var p = new Person(); 429 | ``` 430 | 431 | --- 432 | 433 | ### Or 434 | 435 | ```js 436 | function Person(){ 437 | var that = this; 438 | 439 | this.age = 0; 440 | 441 | setInterval(function() { 442 | that.age++; 443 | }.bind(this), 1000); 444 | } 445 | 446 | var p = new Person(); 447 | ``` 448 | --- 449 | 450 | ### To 451 | 452 | ```js 453 | function Person(){ 454 | this.age = 0; 455 | 456 | setInterval(() => { 457 | this.age++; 458 | }, 1000); 459 | } 460 | 461 | var p = new Person(); 462 | ``` 463 | 464 | --- 465 | 466 | ## Not Covered 467 | 468 | --- 469 | 470 | ## Next time... 471 | 472 | * [binary and octal literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Numeric_literals) 473 | * [new string methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_6_support_in_Mozilla#Additions_to_the_String_object) 474 | * [symbols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol) 475 | * [template strings](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings) 476 | * [object literal extensions](https://github.com/lukehoban/es6features#enhanced-object-literals) 477 | 478 | --- 479 | 480 | ## Resources 481 | 482 | --- 483 | 484 | ## Resources 485 | 486 | [https://github.com/tonypujals/demo-iojs-es6](https://github.com/tonypujals/demo-iojs-es6) 487 | 488 | [https://iojs.org/en/es6.html](https://iojs.org/en/es6.html) 489 | 490 | [http://davidwalsh.name/es6-io](http://davidwalsh.name/es6-io) 491 | 492 | [https://github.com/lukehoban/es6features](https://github.com/lukehoban/es6features) 493 | 494 | [http://www.2ality.com](http://www.2ality.com/2014/08/es6-today.html) 495 | 496 | [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) 497 | --------------------------------------------------------------------------------