ES6 - Next Generation Javascript

8,201 views
7,849 views

Published on

A brief look at the new features coming in Javascript ES6:

- Scope and control
- Iterators and Generators
- Collections
- Typed objects
- Direct proxies
- Template strings
- API improvements
- Modularity

Published in: Technology
1 Comment
14 Likes
Statistics
Notes
No Downloads
Views
Total views
8,201
On SlideShare
0
From Embeds
0
Number of Embeds
55
Actions
Shares
0
Downloads
115
Comments
1
Likes
14
Embeds 0
No embeds

No notes for slide

ES6 - Next Generation Javascript

  1. 1. ES6 Next Generation Javascript By Ramesh Nair and Grégoire Charvet https://github.com/hiddentao/es6-slides
  2. 2. Speakers Grégoire Charvet (geekingfrog.com) Full time node.js developper Passionate about the web Working on the web for almost 2 years now Ramesh Nair (hiddentao.com) Full time Javascript/Node developper Also worked with PHP, Python, Java, C++ Loves optimizing for performance
  3. 3. Rapid history of javascript
  4. 4. The birth Created in 10 days in 1995 (by Brendan Eich) at Netscape Brought to ECMA a year later to standardize it javaScript has nothing to do with java
  5. 5. Early history ECMAScript 2 in 98, 3 in 99 War with Microsoft -> ES4 has never been adopted In 2005, Microsoft introduced ajax In 2009, all parties agreed to move forward with ES5 + harmony process
  6. 6. Now Javascript most well known implementation of ECMAScript (with ActionScript) Javascript is the assembly of the web Confusing version number, JS 1.8 correspond to ES6
  7. 7. ES6 ES6 work started in 2011 As of now (Feb 2014), ES6 is not yet adopted (but it's almost there) Major milestone Not 'production ready' yet
  8. 8. What we will cover today Support Scope and control Iterators and Generators Collections Typed objects Direct proxies Template strings API improvements Modularity
  9. 9. Support 24 30 ✗ For chrome, need to enable the experimental js features full table
  10. 10. Node.js support Node.js: get the latest 0.11 and add the flag --harmony Support is the same as chrome (V8)
  11. 11. Safari support Almost the same as IE (so quasi inexistant)
  12. 12. Scoping 24 30 11
  13. 13. Block scoping Finally !
  14. 14. Before for(var i=10; i>0 ; i--) { // do stuff with i } console.log(i); // 0
  15. 15. let for(let i=10; i>10; i--) { } console.log(i); // `i is not defined`
  16. 16. Works with if too var log = function(msg) {}; if(someCond) { let log = Math.log; // do some stuff } log("I'm done here");
  17. 17. Easier closures broken example var a = ['rhum', 'banana', 'nutella']; for(var i = 0, n=a.length; i<n; i++) { var nomnom = a[i]; setTimeout(function() { console.log(nomnom); }, 500*(i+1)) }
  18. 18. Easy fix var a = ['rhum', 'banana', 'nutella']; for(var i = 0, n=a.length; i<n; i++) { let nomnom = a[i]; setTimeout(function() { console.log(nomnom); }, 500*(i+1)) }
  19. 19. let('s) recap works like var scope is defined by the current block ({ })
  20. 20. const Like let , but define read-only constant declarations. 'use strict'; const i = 10; i = 5; // throw error
  21. 21. Destructuration 24 ✗ ✗
  22. 22. With array // Assignment var [day, month, year] = [19, 02, 2014]; // Swap two values. var x=3, y=4; [x, y] = [y, x];
  23. 23. Array with functions var now = function() { return [19, 02, 2014]; } var [day, month] = now(); var [, , year] = now();
  24. 24. With objects var now = function() { return { d: 19, m: 2, y: 2014 }} var {d: day, m: month} = now(); // day: 19 // month: 2
  25. 25. As argument of a function recipes = [ { name: 'burger', calorie: 215 }, { name: 'pizza', calorie: 266 } ]; recipes.forEach(function ({ name: name, calorie: calorie }) { console.log(name, calorie); } );
  26. 26. Default function parameters 24 30 ✗
  27. 27. Ability to define default value for functions paramaters. No more: function(a) { if(!a) { a = 10; } // do stuff with a }
  28. 28. Now function(a=10) { // do stuff with a }
  29. 29. Undefined and null undefined will trigger the evaluation of the default value, not null function point (x, y=1, z=1) { return console.log(x, y, z); } point(10, null); // 10, null, 1
  30. 30. Arity Number of parameters without default value (function(a){}).length // 1 (function(a=10){}).length // 0 (function(a=10, b){}).length // 1
  31. 31. Rest parameters 24 ✗ ✗
  32. 32. Better than arguments function(name) { console.log(name); arguments[0] = 'ME !'; console.log(name); // ME ! Array.isArray(arguments); // false }
  33. 33. Now function(...args) { Array.isArray(args); // true // do some stuff } function(name, ...more) { }
  34. 34. Example var humblify = function(name, ...qualities) { console.log('Hello %s', name); console.log('You are '+qualities.join(' and ')); } humblify('Greg', 'awesome', 'the master of the universe'); // Hello Greg // You are awesome and the master of the universe
  35. 35. Restrictions Rest parameters can only be the last parameter // incorrect function(...args, callback) { }
  36. 36. Details Rest parameter is always an array function f(name, ...more) { Array.isArray(more); // always true return more.length; } f(); // returns 0
  37. 37. Arity Does not include the rest parameter (function(a) {}).length // 1 (function(a, ...rest) {}).length // 1
  38. 38. Spread 24 (with array) 27-28 (with functions) ✗ ✗
  39. 39. Expand expression where multiple arguments or multiple element are needed
  40. 40. More powerful array manipulation Usecase: create new array with an existing one inside it: var from = [1, 2]; // wants: [0, 1, 2, 3] ie [0, from, 3]
  41. 41. With es5 a.unshift(0); a.push(3); // and splice is here also With es6 var total = [0, ...from, 3];
  42. 42. Converting any array-like
  43. 43. Array like ??? Object with a length property Can access elements with [] var fake = { 0: 'I am', 1: 'not', 2: 'an aray', length: 3 };
  44. 44. Array like in the wild Function's arguments All nodeList from the DOM
  45. 45. Before: var nodes = document.querySelectorAll('p'); var nodes = [].slice.call(nodes); And now: nodes = [...nodes];
  46. 46. Array conversion Better way: Array.from(document.querySelectorAll('p')); Out of the scope of the talk.
  47. 47. Spread with functions A better apply var f = function(one, two, three) {} var a = [1, 2, 3]; f.apply(null, a);
  48. 48. Apply ? Function.prototype.apply fun.apply(thisArg, [argsArray])
  49. 49. Apply example function f() { for(let i=0; i<arguments.length; ++i) console.log(arguments[i]); } f.apply(this, ['one', 2, 'foo']); // one // 2 // foo
  50. 50. With es6's spread var f = function(one, two, three) {} var a = [1, 2, 3]; f(...a);
  51. 51. Sweet syntax var f = function(a, b, c, d, e, f) {}; var a = [1, 2]; f(-1, ...a, 3, ...[-3, -4]);
  52. 52. Apply for new With es5, one cannot use apply with new . var Constructor = function() { // do some stuff } var c = new Constructor.apply({}, []); //invalid But now: var dataFields = readDateFields(database); var d = new Date(...dateFields);
  53. 53. Better push To push multiple elements: var a = []; var toPush = [1, 2, 3]; a.push.apply(a, toPush); And now: a.push(...toPush);
  54. 54. Next... Iterators 24 ✗ ✗
  55. 55. An iterator lets you iterate over the contents of an object. In ES6, an iterator is an object with a next() method which returns {done, value} tuples. An iterable is an object which can return an iterator.
  56. 56. Arrays are iterable: var a = [1,2,3], i = a.iterator(); console.log(i.next()); console.log(i.next()); console.log(i.next()); console.log(i.next()); // // // // {done: {done: {done: {done: false, value: 1} false, value: 2} false, value: 3} true, value: undefined}
  57. 57. The for-of loop can be used to simplify iterations: var a = [1,2,3]; for (var num of a) { console.log(num); // 1, 2, 3 }
  58. 58. Array comprehensions: var a = [ { color: 'red' }, { color: 'blue' } ]; [ x.color for (x of a) if ('blue' === x.color) ] // [ 'blue' ]
  59. 59. We can make any object iterable: function ClassA() { this.elements = [1, 2, 3]; }
  60. 60. By adding the @@iterator method: ClassA.prototype['@@iterator'] = function() { return { elements: this.elements, index: 0, next: function() { if (this.index >= this.elements.length) return { done: true, value: undefined }; else return { done: false, value: this.elements[this.index++] }; }}};
  61. 61. We can iterate over the Object: var col = new ClassA(); for (var num of col) { console.log(num); // 1, 2, 3 }
  62. 62. Generators 27 30 ✗
  63. 63. A generator is a special type of iterator. A generator provides a throw() method. Its next() method accepts a parameter. A generator function acts as a constructor for a generator. Generators offer a clean way of doing asynchronous programming!
  64. 64. Simple example: var helloWorld = function*() { yield 'hello'; yield 'world'; } var hw = helloWorld(); console.log( hw.next() ); // { value: 'hello', done: false } console.log( hw.next() ); // { value: 'world', done: false } console.log( hw.next() ); // { value: undefined, done: true }
  65. 65. Passing values back to generator: var helloWorld = function*() { var nextWord = yield 'hello'; yield nextWord; } var hw = helloWorld(); console.log( hw.next() ); // { value: 'hello', done: false } console.log( hw.next('world') ); // { value: 'world', done: false } console.log( hw.next() ); // { value: undefined, done: true }
  66. 66. Let's take it step-by-step to see how code gets suspended...
  67. 67. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.next('world') ); console.log( hw.next() );
  68. 68. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.next('world') ); console.log( hw.next() );
  69. 69. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.next('world') ); console.log( hw.next() );
  70. 70. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.next('world') ); console.log( hw.next() );
  71. 71. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.next('world') ); console.log( hw.next() );
  72. 72. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.next('world') ); console.log( hw.next() ); Yield 1...
  73. 73. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.next('world') ); console.log( hw.next() ); Yield 1...
  74. 74. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.next('world') ); console.log( hw.next() ); Yield 1... { done: false, value: 'hello' }
  75. 75. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.next('world') ); console.log( hw.next() ); Yield 1... { done: false, value: 'hello' }
  76. 76. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.next('world') ); console.log( hw.next() ); Yield 1... { done: false, value: 'hello' }
  77. 77. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.next('world') ); console.log( hw.next() ); Yield 1... { done: false, value: 'hello' } Yield 2...
  78. 78. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.next('world') ); console.log( hw.next() ); Yield 1... { done: false, value: 'hello' } Yield 2...
  79. 79. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.next('world') ); console.log( hw.next() ); Yield 1... { done: false, value: 'hello' } Yield 2... { done: false, value: 'world' }
  80. 80. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.next('world') ); console.log( hw.next() ); Yield 1... { done: false, value: 'hello' } Yield 2... { done: false, value: 'world' }
  81. 81. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.next('world') ); console.log( hw.next() ); Yield 1... { done: false, value: 'hello' } Yield 2... { done: false, value: 'world' } No more yields...
  82. 82. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } Yield 1... { done: false, value: 'hello' } Yield 2... { done: false, value: 'world' } No more yields... { done: true, value: undefined } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.next('world') ); console.log( hw.next() );
  83. 83. The code in the generator doesn't start executing until you say so. When the yield statement is encountered it suspends execution until you tell it to resume. What about throw() -ing errors?
  84. 84. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.throw('Voldemort') ); console.log( hw.next() );
  85. 85. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.throw('Voldemort') ); console.log( hw.next() );
  86. 86. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.throw('Voldemort') ); console.log( hw.next() );
  87. 87. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.throw('Voldemort') ); console.log( hw.next() );
  88. 88. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.throw('Voldemort') ); console.log( hw.next() ); Yield 1...
  89. 89. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.throw('Voldemort') ); console.log( hw.next() ); Yield 1...
  90. 90. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.throw('Voldemort') ); console.log( hw.next() ); Yield 1... { done: false, value: 'hello' }
  91. 91. var helloWorld = function*() { console.log('Yield 1...'); var nextWord = yield 'hello'; console.log('Yield 2...'); yield nextWord; console.log('No more yields...'); } var hw = helloWorld(); console.log( hw.next() ); console.log( hw.throw('Voldemort') ); console.log( hw.next() ); Yield 1... { done: false, value: 'hello' } Error: Voldemort
  92. 92. How do Generators make asynchronous programming easier?
  93. 93. The old-school way: var readFile = function(fileName, cb) { ... }; var main = function(cb) { readFile('file1', function(err, contents1) { if (err) return cb(err); console.log(contents1); readFile('file2', function(err, contents2) { if (err) return cb(err); console.log(contents2); cb(); }); }); } main(console.error);
  94. 94. Improved using Promises: var readFile = Promise.promisify(function(fileName, cb) { ... }); var main = function() { return readFile('file1') .then(function(contents) { console.log(contents); return readFile('file2'); }) .then(function(contents) { console.log(contents); }) .catch(console.error); } main();
  95. 95. We can do better with generators. But first we need a function which will automatically handle the yield -ed values and call next() on the generator...
  96. 96. Automatically resolve Promises and call next() : var runGenerator = function(generatorFunction) { var gen = generatorFunction(); var gNext = function(err, answer) { if (err) return gen.throw(err); var res = gen.next(answer); if (!res.done) { Promise.resolve(res.value) .then(function(newAnswer) { gNext(null, newAnswer); }) .catch(gNext); } }; gNext(); }
  97. 97. Now we can rewrite main() as a generator function: var readFile = Promise.promisify(function(fileName, cb) { ... }); var main = function*() { try { console.log( yield readFile('file1') ); console.log( yield readFile('file2') ); } catch (err) { console.error(err); } } runGenerator(main);
  98. 98. You don't need to write runGenerator() yourself. https://github.com/visionmedia/co - similar to runGenerator but more powerful. https://github.com/petkaantonov/bluebird - kick-ass Promise library and provides runGenerator-like methods.
  99. 99. Generator delegation: var inner = function*() { try { yield callServer1(); yield callServer2(); } catch (e) { console.error(e); } }; var outer = function*() { try { yield callServer1(); yield callServer2(); } catch (e) { console.error(e); } }; var outer = function*() { yield* inner(); }; runGenerator(outer); runGenerator(outer);
  100. 100. Generator comprehension: (for (x of a) for (y of b) x * y) (function* () { for (x of a) { for (y of b) { yield x * y; } } }())
  101. 101. Generators = future of JS asynchronous programming. ...and ES6 also has Promises! http://spion.github.io/posts/why-i-am-switching-topromises.html
  102. 102. Next... Collections 24 30 11
  103. 103. Set - no duplicates allowed var items = new Set(); items.add(5); items.add("5"); items.add(5); console.log(items.size); // 2 var items = new Set([1,2,3,4,5,5,5]); console.log(items.size); // 5
  104. 104. Modifying a Set var items = new Set([1,2,3,4,4]); console.log( items.has(4) ); // true console.log( items.has(5) ); // false items.delete(4); console.log( items.has(4) ); // false console.log( items.size ); // 3 items.clear(); console.log( items.size ); // 0
  105. 105. Iterate over a Set using for-of var items = new Set([1,2,3,4,4]); for (let num of items) { console.log( num ); } // 1, 2, 3, 4
  106. 106. Map - map from key to value var map = new Map(); map.set("name", "John"); map.set(23, "age"); console.log( map.has(23); ) // true console.log( map.get(23) ); // "age" console.log( map.size ); // 2
  107. 107. Map vs Object Maps can have non-string keys Maps don't have prototype leakage issues, i.e. no need to use hasOwnProperty() But
  108. 108. Modifying a Map var map = new Map([ ['name', 'John'], [23, 'age'] ]); console.log( map.size ); // 2 map.delete(23); console.log( map.get(23) ); // undefined map.clear(); console.log( map.size ); // 0
  109. 109. Iterating over a Map var map = new Map([ ['name', 'John'], [23, 'age'] ]); for (var value of map.values()) { ... } for (var key of map.keys()) { ... } for (var item of map.items()) { console.log('key: ' + item[0] + ', value: ' + item[1]); } for (var item of map) { // same as iterating map.items() } map.forEach(function(value, key, map) { ... });
  110. 110. WeakMap - similar to Map , but... Only allows Object keys Only holds a reference to the Object used as a key, so it doesn't prevent garbage collection Do no provide a size Cannot be iterated over
  111. 111. var weakMap = new WeakMap(); var key = { stuff: true }; weakMap.set(key, 123); // weakMap contains 1 item delete key; // weakMap is now empty
  112. 112. Next... Typed objects ✗ ✗ ✗
  113. 113. Typed objects are similar to struct objects in C They provide memory-safe, structured access to contiguous data They can expose a binary representation, making serialization/de-serialization easy
  114. 114. Example: represent a 2D point const Point2D = new StructType({ x: uint32, y: uint32 });
  115. 115. Can access the underlying storage of the struct let p = Point2D({x : 0, y : 0}); p.x = 5; let arrayBuffer = Point.storage(p).buffer; typeof arrayBuffer // ArrayBuffer arrayBuffer.byteLength // 8
  116. 116. Hierarchy of typed objects const Corner = new StructType({ point: Point2D }); const Triangle = Corner.dim(3); let t = Triangle([{ point: { x: 0, y: 0 } }, { point: { x: 5, y: 5 } }, { point: { x: 10, y: 0 } }]); t[0].point.x = 5;
  117. 117. A type object and all of its sub objects share the same memory let t = Triangle([{ point: { x: 0, y: 0 } }, { point: { x: 5, y: 5 } }, { point: { x: 10, y: 0 } }]); Triangle.storage(t).buffer.byteLength; // 24
  118. 118. Typed objects use copy-on-write const Corner = new StructType({ point: Point2D }); let p = Point2D({ x: 1, y: 1 }); let c = Corner({ point: {x: 2, y: 2} }); c.point = p; // p gets copied c.point.x = 5; p.x; // 1
  119. 119. Built-in value types uint8, uint8Clamped uint16 uint32 int8 int16 int32 float32 float64 boolean string
  120. 120. Next... Direct proxies 24 ✗ ✗
  121. 121. Direct proxies allows you to intercept calls made to a regular object They can wrap any Object , including Date , Function , etc.
  122. 122. Proxies are meant to work 'transparently' var target = []; var handler = { get: function() {...} }; var p = Proxy(target, handler); Object.prototype.toString.call(p) // "[object Array]" Object.getPrototypeOf(p) // Array.prototype typeof p // "object" Array.isArray(p) // true p[0] // triggers handler.get(target, "0", p) p === target // false
  123. 123. Proxy handler can choose what to intercept getOwnPropertyDescriptor getOwnPropertyNames getPrototypeOf defineProperty deleteProperty freeze seal preventExtensions isFrozen isExtensible isSealed has hasOwn get set enumerate keys apply construct
  124. 124. Next... Template strings ✗ ✗ ✗
  125. 125. What template strings allow Multi-line strings String formatting - think printf from C HTML escaping Localization/internationalization
  126. 126. Basic substitution var name = "Tom", msg = `Hello, ${name}!`; console.log(msg); // "Hello, Tom!"
  127. 127. Expressions var total = 30, msg = `The total is ${total * 2} units`; console.log(msg); // "The total is 60 units"
  128. 128. Multi-line var total = 30, var msg = `The total is ${total * 2} units`;
  129. 129. Functions // Gets called with: // ['Total is ', ' units'] // 60 var myFunc = function(literals) { var str = '', i = 0; while (i < literals.length) { str += literals[i++]; if (i < arguments.length) { str += '[' + arguments[i] + ']'; } } return str; }; var total = 30; console.log( myFunc`Total is ${total * 2} units` ); // Total is [60] units
  130. 130. Next... API improvements 24 ✗ ✗ with a few exceptions (full details)
  131. 131. New Math functions log10 , log2 , log1p , expm1 , cosh , sinh , tanh , acosh , asinh , atanh , hypot , trunc , sign
  132. 132. Number .isFinite() .isNaN() - better than isNaN() .isInteger() .EPSILON - smallest values such that 1 + Number.EPSILON > 1
  133. 133. String .repeat(n) - copy current string n times .startsWith(str) .endsWith(str) .contains(str) .toArray() - same as .split('')
  134. 134. Next... Modularity ✗ ✗ ✗
  135. 135. Classes
  136. 136. In es5 Classes doesn't exist natively Prototype based inheritance Framework and libraries implement their own class system
  137. 137. New keyword class Laptop { constructor() { this.brand = 'asus'; } on() { ... } off() { ... } }
  138. 138. Call the parent class SmashedLaptop extend Laptop { constructor() { super(); this.pieces = []; } }
  139. 139. Key points constructor replace the function definition in es5 No access to the prototype of the class Methods are defined the same way as objects Can call the parent with super (and perform initialization within the constructor)
  140. 140. Modules • import the default export of a module import $ from "jquery"; • binding an external module to a variable module crypto from "crypto"; • binding a module's exports to variables import { encrypt, decrypt } from "crypto";
  141. 141. Modules • binding & renaming one of a module's exports import { encrypt as enc } from "crypto"; • re-exporting another module's exports export * from "crypto"; • re-exporting specified exports from another module export { foo, bar } from "crypto";
  142. 142. Why ? No need for the global object anymore Works well with existing modules system (AMD, CommonJS and node) Simplicity and usability Compatibility with browser and non-browser environments Easy asynchronous external loading
  143. 143. Exporting and importing module "chocolate" { export let cocoa = 75; } In another file: import { cocoa } from "chocolate"; // or import { cocoa as c} from "chocolate";
  144. 144. Default export module "foo" { export default function() {console.log("Hi")} } import foo from "foo"; // no brackets foo(); // Hi
  145. 145. Internals Top-level variables stay inside the module export make variables visible to the other modules Can be read (get) Cannot be changed (set) Cannot be dynamically changed at runtime Modules are recursively instantiated before evaluation Modules' body is run after all dependencies are instantiated
  146. 146. That's all for today! See http://kangax.github.io/es5-compat-table/es6/ for more
  147. 147. Useful links http://www.ecmascript.org/ http://www.esdiscuss.org/ https://developer.mozilla.org/en/docs/Web/JavaScript/ECMAScript

×