$30 off During Our Annual Pro Sale. View Details »

JavaScript: Past, Present, and Future

JavaScript: Past, Present, and Future

Ah, JavaScript! Like it or not, it's a "tragically important" language that is "eating the world." Hate it? Love it? Avoid it? Embrace it?

This talk will be a parade of face-palm JavaScript fails, stupid JavaScript tricks, and bad jokes sure to get an eye-roll from everyone! Along the way, we may even learn a few mistakes to avoid and tips to make our own JavaScript less terrible!

David Neal

April 08, 2022
Tweet

More Decks by David Neal

Other Decks in Programming

Transcript

  1. None
  2. None
  3. None
  4. None
  5. None
  6. None
  7. None
  8. None
  9. None
  10. None
  11. None
  12. > const lol = a + b + c –

    f * ( n + o ); NaN
  13. > NaN >= 0 false

  14. > NaN <= 0 false

  15. > typeof NaN number

  16. ( a + b ) + c = a +

    ( b + c ) // mathematically true > 0.1 + 0.2 === 0.3 false > ( a + b ) + c == a + ( b + c ) ??
  17. > 0.1 + 0.2 0.30000000000000004

  18. > Math.round(0.4999999999999999722444243843710864894092082) 0 > Math.round(0.4999999999999999722444243843710864894092083) 1 I’ve got 99 problems

    but JavaScript ain’t 1.0000000000000009
  19. > [ 2, 10 ].sort() [ 10, 2 ]

  20. > ['10','10','10', '10', '10'].map( parseInt ) [ 10, NaN, 2,

    3, 4 ]
  21. > typeof undefined // undefined > typeof true // boolean

    > typeof "hello" // string > typeof 1 // number > typeof {lol:true} // object > typeof [1,2,3] // object > typeof null // object
  22. > null == 0 // false > null > 0

    // false > null < 0 // false > null >= 0 // true > null <= 0 // true > Number( null ) // 0
  23. > false > null > undefined > "" > 0

    > NaN
  24. > wat.test("javascript"); // true > wat.test("wat r u doin"); //

    false > const wat = /a/g;
  25. // undefined function troll() { return { haha: "ha!" };

    } troll(); // automatic semi-colon
  26. const arr = []; arr[1] = 1; arr[3] = 2;

    arr[10] = 3; arr.length // 11 arr[-1] = 4; arr.s = 5; arr.length // 11
  27. None
  28. None
  29. None
  30. None
  31. None
  32. None
  33. None
  34. None
  35. None
  36. None
  37. None
  38. None
  39. None
  40. None
  41. None
  42. None
  43. None
  44. None
  45. None
  46. None
  47. None
  48. None
  49. None
  50. None
  51. None
  52. None
  53. None
  54. None
  55. None
  56. None
  57. None
  58. None
  59. None
  60. None
  61. None
  62. None
  63. None
  64. None
  65. None
  66. None
  67. None
  68. None
  69. None
  70. None
  71. None
  72. None
  73. None
  74. None
  75. None
  76. None
  77. None
  78. None
  79. None
  80. None
  81. None
  82. None
  83. None
  84. None
  85. None
  86. None
  87. None
  88. None
  89. None
  90. None
  91. None
  92. None
  93. None
  94. • trimStart() and trimEnd() • Optional Catch • Object.fromEntries() •

    flat() and flatMap()
  95. // String.prototype.trimStart() and trimEnd() const what = " \n \t

    what is love".trimStart(); const bacon = "bacon don't hurt me\n \n \n \t ".trimEnd(); const obj = { lyric: what + " " + bacon }; console.log( obj ); // { lyric: "what is love bacon don't hurt me" }
  96. // Optional Catch try { console.log( "Error objects?" ); throw

    new Error( "LOL" ); } catch { console.log( "We don't need no stinkin' Error objects!" ); } // Error objects? // We don't need no stinkin' Error objects!
  97. // Object.fromEntries() const props = [ [ "what", "is love"

    ], [ "bacon", "don't hurt me" ], [ "love", true ] ]; const obj = Object.fromEntries( props ); console.log( obj ); // { what: 'is love', bacon: "don't hurt me", love: true }
  98. // Array.prototype.flat() and .flatMap() const nestedArrays = [ "bacon", "eggs",

    [ "waffles" ], [ "coffee" ], [ "doughnuts", "milk" ] ]; const flattened = nestedArrays.flat(); console.log( flattened ); // [ 'bacon', 'eggs', 'waffles', 'coffee', 'doughnuts', 'milk' ]
  99. • Nullish coalescing ?? operator • Optional ?. chaining •

    Promise.allSettled() • Dynamic import()
  100. // Logical OR || operator works with any falsy value

    console.log( 0 || "zero value" ); // zero value console.log( "" || "empty string value" ); // empty string value console.log( false || "false value" ); // false value console.log( null || "null value" ); // null value console.log( undefined || "undefined value" ); // undefined value
  101. // Nullish (??) operator only works with null/undefined console.log( 0

    ?? "zero value" ); // 0 console.log( "" ?? "empty string value" ); // "" console.log( false ?? "false value" ); // false console.log( null ?? "null value" ); // null value console.log( undefined ?? "undefined value" ); // undefined value
  102. // The old way of checking for potentially missing properties

    const customer = {}; let city; try { city = customer.address.city; } catch ( err ) { console.log( err ); // TypeError: Cannot read properties of undefined (reading 'city’) } console.log( city ); // undefined
  103. // The old way of checking for potentially missing properties

    const customer = {}; let city; if ( customer && customer.address && customer.address.city ) { city = customer.address.city; } console.log( city ); // undefined
  104. // Optional ?. Chaining const customer1 = {}; const customer2

    = { address: { city: "Nashville" } }; const city1 = customer1?.address?.city; // undefined const city2 = customer2?.address?.city; // Nashville
  105. // Promise.allSettled() const p1 = new Promise( ( resolve, reject

    ) => { setTimeout( () => { resolve( "p1 resolved" ); }, 250 ); } ); const p2 = new Promise( ( resolve, reject ) => { setTimeout( () => { resolve( "p2 resolved" ); }, 450 ); } ); const p3 = new Promise( ( resolve, reject ) => { setTimeout( () => { reject( "p3 rejected" ); }, 650 ); } );
  106. // Promise.allSettled() const results = await Promise.allSettled( [ p1, p2,

    p3 ] ); console.log( results ); // [ // { status: 'fulfilled', value: 'p1 resolved' }, // { status: 'fulfilled', value: 'p2 resolved' }, // { status: 'rejected', reason: 'p3 rejected' } // ]
  107. // Dynamic import() const example = await import( "./importExample.js" );

    console.log( example ); // [Module: null prototype] { // default: { whatIsLove: [Function: whatIsLove] } // }
  108. • String.prototype.replaceAll() • Promise.any() • Logical assignment operators ||= &&=

    ??= • Numeric separator
  109. // Old string replace() const qs = "q=what+is+love"; const nope

    = qs.replace( "+", " " ); // "q=what is+love”
  110. // Old string replace() const qs = "q=what+is+love"; const nope

    = qs.replace( "+", " " ); // "q=what is+love” const yep = qs.replace( /\+/g, " " ); // "q=what is love"
  111. // Old string replace() const qs = "q=what+is+love"; const nope

    = qs.replace( "+", " " ); // "q=what is+love” const yep = qs.replace( /\+/g, " " ); // "q=what is love" const lol = qs.split( "+" ).join( " " ); // "q=what is love"
  112. // String.prototype.replaceAll() const n00b = "Hey, I can leet speak,

    too, yo"; const l33t = n00b.replaceAll( "e", "3" ) .replaceAll( "o", "0" ) .replaceAll( ",", "" ) .toLowerCase(); console.log( l33t );
  113. // String.prototype.replaceAll() const n00b = "Hey, I can leet speak,

    too, yo"; const l33t = n00b.replaceAll( "e", "3" ) .replaceAll( "o", "0" ) .replaceAll( ",", "" ) .toLowerCase(); console.log( l33t ); // h3y i can l33t sp3ak t00 y0
  114. // Promise.any() example const p1 = new Promise( res =>

    { setTimeout( () => { res( "knock, knock" ); }, 200 ); } ); const p2 = new Promise( res => { setTimeout( () => { res( "who's there?" ); }, 400 ); } ); const interruptingCow = Promise.reject( "MOO!!" ); const lol = await Promise.any( [ p1, p2, interruptingCow ] ); console.log( lol );
  115. // Promise.any() example const p1 = new Promise( res =>

    { setTimeout( () => { res( "knock, knock" ); }, 200 ); } ); const p2 = new Promise( res => { setTimeout( () => { res( "who's there?" ); }, 400 ); } ); const interruptingCow = Promise.reject( "MOO!!" ); const lol = await Promise.any( [ p1, p2, interruptingCow ] ); console.log( lol ); // knock, knock
  116. // Logical assignment operators // OR only assigns if x

    is a falsy value let x = false; x ||= "yes"; x ||= "what is";
  117. // Logical assignment operators // OR only assigns if x

    is a falsy value let x = false; x ||= "yes"; x ||= "what is"; // yes
  118. // Logical assignment operators // OR only assigns if x

    is a falsy value let x = false; x ||= "yes"; x ||= "what is"; // yes // AND assigns if y is not a falsy value let y = "gimme-all-yer"; y &&= "i love";
  119. // Logical assignment operators // OR only assigns if x

    is a falsy value let x = false; x ||= "yes"; x ||= "what is"; // yes // AND assigns if y is not a falsy value let y = "gimme-all-yer"; y &&= "i love"; // i love
  120. // Logical assignment operators // OR only assigns if x

    is a falsy value let x = false; x ||= "yes"; x ||= "what is"; // yes // AND assigns if y is not a falsy value let y = "gimme-all-yer"; y &&= "i love"; // i love // ??= Nullish only assigns if z is null or undefined let z = "bacon"; z ??= y;
  121. // Logical assignment operators // OR only assigns if x

    is a falsy value let x = false; x ||= "yes"; x ||= "what is"; // yes // AND assigns if y is not a falsy value let y = "gimme-all-yer"; y &&= "i love"; // i love // ??= Nullish only assigns if z is null or undefined let z = "bacon"; z ??= y; // bacon
  122. // Numeric separators example const numbersMakeMeSad = 10204005020405;

  123. // Numeric separators example const numbersMakeMeSad = 10204005020405; const notSoBad

    = 10_204_005_020_405;
  124. // Numeric separators example const numbersMakeMeSad = 10204005020405; const notSoBad

    = 10_204_005_020_405; console.log( numbersMakeMeSad === notSoBad ); // true
  125. • Array.prototype.at() & String .at() • Top-level await • Error

    cause • New static, private class members
  126. // String and Array at() const arr = [ "what",

    "is", "love", "bacon", "don't", "hurt", "me" ]; console.log( arr.at( 3 ) );
  127. // String and Array at() const arr = [ "what",

    "is", "love", "bacon", "don't", "hurt", "me" ]; console.log( arr.at( 3 ) ); // bacon
  128. // String and Array at() const arr = [ "what",

    "is", "love", "bacon", "don't", "hurt", "me" ]; console.log( arr.at( 3 ) ); // bacon console.log( arr.at( -1 ) );
  129. // String and Array at() const arr = [ "what",

    "is", "love", "bacon", "don't", "hurt", "me" ]; console.log( arr.at( 3 ) ); // bacon console.log( arr.at( -1 ) ); // me
  130. // String and Array at() const arr = [ "what",

    "is", "love", "bacon", "don't", "hurt", "me" ]; console.log( arr.at( 3 ) ); // bacon console.log( arr.at( -1 ) ); // me const msg = "I love rock n' roll"; console.log( msg.at( 4 ) );
  131. // String and Array at() const arr = [ "what",

    "is", "love", "bacon", "don't", "hurt", "me" ]; console.log( arr.at( 3 ) ); // bacon console.log( arr.at( -1 ) ); // me const msg = "I love rock n' roll"; console.log( msg.at( 4 ) ); // v
  132. // Top-level await async function sleep( ms ) { const

    msg = `I slept for ${ ms } milliseconds`; return new Promise( resolve => setTimeout( () => resolve( msg ), ms ) ); } const result = await sleep( 500 ); console.log( result ); console.log( "finished" );
  133. // Top-level await async function sleep( ms ) { const

    msg = `I slept for ${ ms } milliseconds`; return new Promise( resolve => setTimeout( () => resolve( msg ), ms ) ); } const result = await sleep( 500 ); console.log( result ); console.log( "finished" ); // I slept for 500 milliseconds // finished
  134. // Error _with_ a cause function breakin() { throw new

    Error( "Gonna stop you cold" ); } function breakin2ElectricBoogaloo() { try { breakin(); } catch ( err ) { throw new Error( "Whacked", { cause: err } ); } }
  135. // Error _with_ a cause function shutUpAndDance() { try {

    breakin2ElectricBoogaloo(); } catch ( err ) { console.log( err ); } } shutUpAndDance();
  136. // Error _with_ a cause shutUpAndDance(); // Error: Whacked //

    at breakin2ElectricBoogaloo ... // [cause]: Error: Gonna stop you cold // at breakin ... // }
  137. // Private and static class members class Of86GlenbrookNorthHigh { #reason;

    static car = "Ferrari"; static #miles = 26000; constructor( reason ) { this.#reason = reason; } ... }
  138. // Private and static class members class Of86GlenbrookNorthHigh { #reason;

    static car = "Ferrari"; static #miles = 26000; static #getMiles() { Of86GlenbrookNorthHigh.#miles += 123; return Of86GlenbrookNorthHigh.#miles; } }
  139. // Private and static class members class Of86GlenbrookNorthHigh { #reason;

    static car = "Ferrari"; static #miles = 26000; static #getMiles() { … } #carStatus() { const miles = Of86GlenbrookNorthHigh.#getMiles(); return `The ${ Of86GlenbrookNorthHigh.car } has ${ miles } miles`; } }
  140. // Private and static class members class Of86GlenbrookNorthHigh { #carStatus()

    { … } status() { console.log( `Ferris can't go to school, he's ${ this.#reason }` ); console.log( this.#carStatus() ); } }
  141. // Private and static class members const myClass = new

    Of86GlenbrookNorthHigh( "sick" ); myClass.status(); // Ferris can't go to school, he's sick // The Ferrari has 26123 miles
  142. // Private and static class members const myClass = new

    Of86GlenbrookNorthHigh( "sick" ); myClass.status(); myClass.#carStatus(); // SyntaxError console.log( myClass.#car ); // SyntaxError
  143. None
  144. None
  145. None
  146. None
  147. None
  148. None
  149. None
  150. None
  151. None
  152. None
  153. None
  154. None
  155. None
  156. None
  157. None
  158. None
  159. None
  160. None
  161. None
  162. None
  163. None
  164. None