Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ES6 Intro

ES6 Intro

Gentle introduction to main ES6 features.

A lot of inspiration for the slides comes from a great book "You Don't Know JS - ES6 & Beyond" by Kyle Simpson

Avatar for David Krmpotic

David Krmpotic

October 30, 2015
Tweet

Other Decks in Programming

Transcript

  1. Forward • Version labels stop being as important, and JavaScript

    starts to be seen more as a living standard. • ESXXXX - new label, eg. ES2016 • Whatever labels that future JavaScript adopts, it’s going to move a lot quicker than it ever has before. Transpilers and shims/polyfills are important tools to keep you on the forefront of where the language is headed.
  2. • Try online
 http://babeljs.io/repl • npm package
 npm install --global

    babel
 babel script.js
 babel-node script.js • SublimeText
 you can add to Sublime Build system
 execute with ⌘B
  3. More babel • Compile
 babel script.js
 # output… • To

    file
 babel script.js -o script-compiled.js • Watch + compile
 babel script.js -w -o script-compiled.js
  4. babel-node • REPL
 babel-node • Evaluate code
 babel-node -e "class

    Test { }" • Compile and run
 babel-node test[.js]
  5. Strict mode • Strict mode makes several changes 
 to

    normal JavaScript semantics. • Eliminates some JavaScript silent 
 errors by changing them to throw errors. • Fixes mistakes that make it difficult for JavaScript engines to perform optimizations. • Prohibits some syntax likely to be defined in future versions of ECMAScript. "use strict" function x() { ... } ...
  6. Plan • let keyword • const keyword • shorthand object

    notation • default parameters • arrow functions • spread operator • template literals • destructuring • concise methods • computed properties • symbols • for..of loop • modules • classes • promises
  7. The more I learn the deeper in I'm drawn The

    deeper in I fall Out Of Nowhere by Shadow Gallery
  8. let ES6 let: block scope! function hello() { if(true) {

    let text = "HELLO" } console.log(text) } ReferenceError: text is not defined function hello() { if(true) { var text = "HELLO" } console.log(text) } global scope or function scope This “works”, it prints “HELLO” Currently:
  9. function hello() { for(let i = 0; i < 10;

    i++) { console.log("HELLO") } console.log(i) } Another let example: ReferenceError: i is not defined
  10. const const is block scoped as well… const planet =

    "Mars" planet = "Pluto" SyntaxError: “planet” is read-only const o = { a: 5, b: 10 } o.a = 20 console.log(o.a) // 20 This is ok, only the variable asignment is fixed, not the value
  11. Shorthand object notation var name = "Angela" var age =

    61 var person = { name, age } console.log(person.name) // Angela var person = { name: name, age: age }
  12. Default parameters function hi(name = "John") { return `Hi ${name}`

    } hi() // Hi John hi("Janet") // Hi Janet hi(undefined) // Hi John hi(null) // Hi null !
  13. Can be value expressions function generateName() { return "Boris" }

    function hi(name = generateName()) { return "Hi " + name } console.log(hi()) // Hi Boris (lazy evaluation)
  14. Arrow functions Syntax: • implicit return if only one expression

    (no curly braces) • (..) needed unless exactly one parameter Behaviour: • scope inherited from parent (explained in the next slide) function sum(a, b) { return a + b } let sum = (a, b) => a + b let numbers = [1, 2, 3] numbers.map(x => x * x) // [ 1, 4, 9 ] setTimeout(() => { console.log("OH") console.log("HI") }, 500)
  15. Current scope in callbacks let person = { name: "Elisabeth",

    identify: function() { setTimeout(function() { console.log(this.name) }, 500) } } person.identify() // after 500ms: // Elisabeth let person = { name: "Elisabeth", identify: function() { var self = this setTimeout(function() { console.log(self.name) // Elisabeth }, 500) } } Hack undefined!
  16. With arrow functions let person = { name: "Elisabeth", identify:

    function() { setTimeout(() => { console.log(this.name) }, 500) } } Lexical scope! inner functions contain the scope of parent (functions) This works now!
  17. Be careful… let person = { name: "Elisabeth", identify: ()

    => { console.log(this.name) } } Fails because this is undefined (node.js) or window object (browser). Arrow function inherited global scope Lesson: not to be used everywhere, normal functions are fine for many purposes
  18. Spread operator let a = [1,2,3] let b = [0,

    ...a, 4] console.log(b) // [ 0, 1, 2, 3, 4 ] Spreads array into individual values: function sum(a, b, c) { return a + b + c } let numbers = [10, 20, 30] sum(...numbers) // 60
  19. Works with objects too let A = { a: 5,

    b: 10 } let B = { b: 15, c: 20 } let C = {...A, ...B} console.log(C) // { a: 5, b: 15, c: 20 } case UPDATE_CAMPAIGN: return { ...state, campaigns: state.campaigns.map(c => c.id == action.payload.id ? { ...c, ...action.payload } : c ) }
  20. Gathers when used in function declaration function sum(name, ...numbers) {

    console.log(`Hi ${name}, summing your numbers now...`) let total = 0 numbers.forEach(function(n) { total += n }) return total } sum("Igor", 10, 20, 30, 40, 50) // 150 sum("Igor") // 0 called rest parameters (always last in function declaration) numbers is an empty array - nice!
  21. Template literals var country = "Slovenia" var greeting = "Hello

    from " + country console.log(greeting) // Hello from Slovenia var country = "Slovenia" var greeting = `Hello from ${country}` console.log(greeting) // Hello from Slovenia
  22. A tagged string literal is like a processing step after

    the interpolations are evaluated but before the final string value is compiled, allowing you more control over generating the string from the literal. Tagged template literals function tag(strings, ...values) { console.log(strings) // [ '', ' + ', ' is ', '' ] console.log(values) // [ 1, 2, 3 ] ... // return something } let a = 1, b = 2 let str = tag `${a} + ${b} is ${a + b}` Great for internationalisation etc…
  23. “Real” example function numify(strings, ...values) { console.log(strings) // [ '',

    ' + ', ' is ', '' ] console.log(values) // [ 1, 2, 3 ] let original = strings.reduce(function(str, current, index) { return str + '<num>' + values[index - 1] + '</num>' + current }) return `<p>${original}</p>` } let a = 1, b = 2 let str = numify `${a} + ${b} is ${a + b}` console.log(str) // <p><num>1</num> + <num>2</num> is <num>3</num></p>
  24. Supports multiline let text = `'Who ARE you talking to?'

    said the King, going up to Alice, and looking at the Cat's head with great curiosity. 'It's a friend of mine - a Cheshire Cat,' said Alice: 'allow me to introduce it.'`
  25. Destructuring function getColors() { return ["red", "green", "blue"] } let

    [c1, c2, c3] = getColors() console.log(c2) // green Array
  26. More var x = 10, y = 20 [y, x]

    = [x, y] console.log( x, y ) // 20, 10 Swap Destructure and gather let a = [2, 3, 4] let [b, ...c] = a console.log(b, c) // 2 [3, 4]
  27. Objects function getMobilePercentages() { return { android: 70, iphone: 29,

    windows: 1 } } let { iphone: iph, windows: win } = getMobilePercentages() console.log(win) // 1
  28. Shorthand notation function getPhonePercentages() { return { android: 70, iphone:

    29, windows: 1 } } let { android, iphone, windows } = getPhonePercentages() console.log(windows) // 1
  29. Default value assignment let [a = 10, b] = [undefined,

    20] console.log(a, b) // 10, 20 let { a: aa = 40, b: bb } = { a: undefined, b: 50 } console.log(aa, bb) // 40, 50
  30. Nested destructuring let App = { model: { User: function()

    { .. } } } let { model: { User} } = App // User: Function var a1 = [1, [2, 3, 4], 5] var o1 = { x: {y: {z: 6 }}} var [a, [b, c, d], e] = a1 var { x: { y: { z: w }}} = o1 console.log(a, b, c, d, e) // 1 2 3 4 5 console.log(w) // 6
  31. Destructuring parameters function printPerson({ name, age }) { console.log(`My name

    is ${name} and I am ${age} years old`) } var person = { name: "Angela", age: 61 } printPerson(person) // My name is Angela and I am 61 years old All previously discussed variations of destructuring are available
  32. Concise methods var person = { getAge: function() { ...

    } } var person = { getAge() { ... } }
  33. Computed properties let prefix = "user_" let o = {

    baz: function(..) { .. }, [ prefix + "foo" ]: function(..) { .. }, [ prefix + "bar" ]: function(..) { .. } .. }
  34. let sym = Symbol("some optional description") typeof sym; // "symbol"

    Symbols Internal unique name is hidden const EVT_LOGIN = Symbol("event.login") EVT_LOGIN holds a value that cannot be duplicated (accidentally or otherwise)
  35. “Hidden” property const INSTANCE = Symbol("instance") function HappyFace() { if

    (HappyFace[INSTANCE]) return HappyFace[INSTANCE] function smile() { .. } return HappyFace[INSTANCE] = { smile: smile } } let me = HappyFace(), you = HappyFace() me === you Not actually hidden but treated as such
  36. Symbols as Object Properties let o = { foo: 42,

    [Symbol( "bar" )]: "hello world", baz: true } console.log(Object.getOwnPropertyNames(o)) // [ "foo","baz" ] console.log(Object.getOwnPropertySymbols(o)) // [ Symbol(bar) ] Symbol property doesn’t show up here
  37. Symbol registry const EVT_LOGIN = Symbol.for("event.login") Finds or creates unique

    symbol based on the string. Accessible from anywhere… But we are back to magic strings… You have to be careful to provide unique strings if you use this.
  38. Built-in symbols let a = [1, 2, 3] a[Symbol.iterator] //

    Function: ArrayValues Symbol.iterator = @@iterator (in specification) Some other: @@toStringTag, @@toPrimitive Mostly used for metaprogramming purposes
  39. var a = ["a", "b", "c", "d", "e"] for(var idx

    in a) { console.log(idx) } // 0 1 2 3 4 for..in (ES5): for..of loop Loops over the keys/indexes in the a array for(let val of a) { console.log(val) } // "a" "b" "c" "d" "e" for..of (new): Loops over values More exactly: loops over the set of values produced by an iterator for( let {x: n} of [ {x: 1}, {x: 2}, {x: 3} ]) { console.log(n) } // 1 2 3 Destructuring in a loop:
  40. Iterable • arrays • strings • generators • collections /

    TypedArrays Plain objects are not by default suitable for for..of looping. That’s because they don’t have a default iterator, which is intentional, not a mistake. let a = [1, 2, 3] let iter = a[Symbol.iterator]() iter.next() // { value: 1, done: false } iter.next() // { value: 2, done: false } iter.next() // { value: 3, done: false } iter.next() // { value: undefined, done: true } for (let v, res; !(res = iter.next()) && !res.done) { v = res.value console.log(v) }
  41. Modules ES6 modules are file-based, meaning one module per file.

    export function foo() { console.log("OH HI") } var awesome = 42 var bar = [1,2,3] export { bar, awesome } export.js import * as moo from "./export" moo.foo() // OH HI console.log(moo.awesome) //42 import { foo } from "./export" foo() // OH HI import.js • All imported bindings are immutable and read-only. • You import references!
  42. Default export export default function foo() { console.log("OH HI") }

    var awesome = 42; var bar = [1,2,3]; export { bar, awesome } import greeter from "./export" greeter() // OH HI export.js import.js
  43. Importing everything import * as moo from "./export" console.log(moo.awesome) //

    42 moo.foo() Error: moo.foo is not a function moo.default() // OH HI import greeter, * as moo from "./export" greeter() // OH HI moo.default() // OH HI ups better and this still works
  44. Classes function Person(name) { this.name = name } Person.prototype.sayHi =

    function() { console.log(“Hi, I’m " + this.name) } var p = new Person("Miro") p.sayHi() // Hi, I’m Miro class Person { constructor(name) { this.name = name } sayHi() { console.log( “Hi, I’m " + this.name) } } var p = new Person("Miro") p.sayHi() // Hi, I’m Miro Class just creates a constructor function of the same name. An ES6 class isn’t really an entity itself, but a meta concept that wraps around other concrete entities like functions and properties and ties them together.
  45. var o1 = { foo() { console.log("o1:foo") } } var

    o2 = { foo() { super.foo() console.log("o2:foo") } } Object.setPrototypeOf(o2, o1) o2.foo() // o1: foo // o2: foo also new in ES6 works only from concise methods super
  46. Prototype inheritance (delegation link between two function prototypes) class Doctor

    extends Person { constructor(name, specialization) { super(name) this.specialization = specialization } sayHi() { super.sayHi() console.log(`I’m a doctor of ${this.specialization}`) } } var d = new Doctor("Bob", "Plastic Surgery") d.sayHi() // Hi, I’m Bob // I'm a doctor of Plastic Surgery
  47. More • Default (if we don’t provide one) subclass constructor

    automatically calls the parent constructor
 
 • In a constructor of a subclass, you cannot access this until super(..) has been called • Extending built-in natives 
 is now possible constructor(...args) { super(...args) } class MyCoolArray extends Array { first() { return this[0] } last() { return this[this.length] } } var a = new MyCoolArray(1, 2, 3) a.first() // 1 a.last() // 3 class Oops extends Error { constructor(reason) { this.oops = reason } } // later: var ouch = new Oops( "I messed up!" ) throw ouch
  48. let p = new Promise(function(resolve, reject) { // resolve and

    reject are functions that we 
 // call upon success or failure }) p.then(function(fulfillment) { // promise fulfilled }).catch(function(reason) { // promise rejected }) // or: p.then( function(fulfillment) { // promise fulfilled }, function(reason) { // promise rejected } ) Promises
  49. Promises are not about replacing callbacks. They provide a trustable

    intermediary to manage callbacks — that is, between your calling code and the async code that will perform the task. The big takeaway is that they offer a significant improvement over callbacks-only async, namely that they provide order, predictability, and trustability. The purpose of promises
  50. function findGold() { return new Promise(function(resolve, reject) { console.log("Searching...") setTimeout(()

    => { let weight = Math.floor(3 * Math.random()) if(weight) { resolve(weight) } else { reject() } }, 1000) }) } findGold().then(function(weight) { console.log(`Found ${weight}kg!`) }).catch(function() { console.log("No gold, sorry, back to work") }) // Searching... // Found 1kg!
  51. There is more… • better regular expressions + unicode •

    generators • collections • API additions (Array.find etc.) let a = ["a", "bb", "ccc"] a.find(x => x.length > 1) // bb
  52. Next • The future ES7 version of JavaScript aims to

    bring many low- level improvements for high-performance and scientific computing, including new value objects, operator overloading, and SIMD intrinsics. New value objects proposed in ES7 include: int64, uint64, int32x4 and int32x8 (SIMD), float32 (useful for GPUs), float32x4 and float32x8 (SIMD), bignum, decimal, rational, and complex. • Support for SIMD (Single Instruction, Multiple Data) will lead to native performance for applications like game programming and signal processing. Recommended talk:
 Brendan Eich on JavaScript Taking Both the High and Low Roads (2014) https://youtu.be/aZqhRICne_M
  53. Resources • You Don’t Know JS: 
 ES6 and Beyond

    
 by Kyle Simpson • http://exploringjs.com/ • https://github.com/airbnb/javascript • ES6 Katas: http://www.mybridge.co/view/3867