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

Javascript’s scary side

Javascript’s scary side

We all know that JavaScript has good parts. But some areas are not for the feint of heart. We hear terms like Prototypes, Hoisting, Closures, Event Loop, and all this weird async/callback behavior. Why in the world would you ever setTimeout to 0, and why can I never rely on ‘this’? In this talk, Jon will show you how all this works…and how to use these tools to your advantage. It’s time to shine a light under the bed of JavaScript. Much like scary monsters under the bed, when the lights come on, the monsters are not so scary after all.

Jonathan Mills

May 01, 2019
Tweet

More Decks by Jonathan Mills

Other Decks in Technology

Transcript

  1. #JSScarySide J AVA S C R I P T ’

    S S C A R Y S I D E @JONATHANFMILLS
  2. None
  3. None
  4. None
  5. None
  6. Types

  7. Types NUMBER STRING BOOLEAN NULL UNDEFINED FUNCTION OBJECT SYMBOL

  8. typeof undefined // "undefined" typeof 0 // "number" typeof true

    // "boolean" typeof “PrDC” // "string"
  9. typeof null

  10. typeof null // object

  11. typeof NaN

  12. typeof NaN // number

  13. console.log(‘1’ + 1); // 11

  14. console.log(1 + 1);

  15. console.log ('Hello ' + 'World');

  16. console.log(‘1’ + 1); // 11

  17. console.log(‘1’ - 1); // 0

  18. console.log(42 + true);

  19. console.log(42 + true); // 43

  20. console.log([1,2,3].indexOf(3));

  21. console.log([1,2,3].indexOf(3)); // 2

  22. console.log(![1,2,3].indexOf(3));

  23. console.log(!![1,2,3].indexOf(3));

  24. console.log(!![1,2,3].indexOf(3)); // True

  25. Hoisting

  26. var myVariable = 10; console.log(myVariable);

  27. var myVariable = 10; console.log(myVariable); // 10

  28. console.log(myVariable); var myVariable = 10;

  29. console.log(myVariable); // undefined var myVariable = 10;

  30. console.log(myVariable);

  31. ReferenceError: myVariable is not defined at Object.<anonymous> (/Users/jonathanmills/Dropbox/Talks/scarySide/2- hoisting.js:3:13) at

    Module._compile (module.js:643:30) at Object.Module._extensions..js (module.js:654:10) at Module.load (module.js:556:32) at tryModuleLoad (module.js:499:12) at Function.Module._load (module.js:491:3) at Function.Module.runMain (module.js:684:10)
  32. console.log(myVariable); // undefined var myVariable = 10;

  33. console.log(myVariable); let myVariable = 10;

  34. console.log(myVariable); // myVariable is not defined let myVariable = 10;

  35. var myVariable = 10; function func(){ myVariable = 25; var

    myVariable; console.log(myVariable); } func(); console.log(myVariable);
  36. var myVariable = 10; function func(){ myVariable = 25; var

    myVariable; console.log(myVariable); // 25 } func(); console.log(myVariable); // 10
  37. var myVariable = 10; function func(){ myVariable = 25; console.log(myVariable);

    } func(); console.log(myVariable);
  38. var myVariable = 10; function func(){ myVariable = 25; console.log(myVariable);

    // 25 } func(); console.log(myVariable); // 25
  39. var myVariable = 10; function func(){ myVariable = 25; let

    myVariable; console.log(myVariable); } func(); console.log(myVariable);
  40. var myVariable = 10; function func(){ myVariable = 25; //

    myVariable is not defined let myVariable; console.log(myVariable); } func(); console.log(myVariable);
  41. Functions

  42. function greeter(name){console.log('Hello ' + name)} greeter('jon');

  43. greeter(‘jon'); function greeter(name){console.log('Hello ' + name)}

  44. greeter(‘jon’); var greeter = function(name){console.log(‘Hello ' + name)}

  45. greeter(‘jon’); // error var greeter = function(name){console.log(‘Hello ' + name)}

  46. function greeter(name){console.log('Hello ' + name)} greeter('jon');

  47. function getGreeter(){ var greeting = 'Hello' return { greeter: function(name){console.log(greeting

    + ' ' + name)} } } var g = getGreeter(); g.greeter(‘Jon');
  48. function getGreeter(){ var greeting = 'Hello' return { greeter: function(name){console.log(greeting

    + ' ' + name)} } } var g = getGreeter(); g.greeter(‘Jon’); // Hello Jon
  49. Closures

  50. function getGreeter(){ var greeting = 'Hello' return { greeter: function(name){console.log(greeting

    + ' ' + name)} } } var g = getGreeter(); g.greeter(‘Jon'); // Hello Jon
  51. function getGreeter(){ var greeting = 'Hello' return { greeter: function(name){console.log(greeting

    + ' ' + name)} } } var g = getGreeter(); var x = g.greeter; x('Jon');
  52. function getGreeter(){ var greeting = 'Hello' return { greeter: function(name){console.log(greeting

    + ' ' + name)} } } var g = getGreeter(); var x = g.greeter; x(‘Jon'); // Hello Jon
  53. This

  54. var greeter = { greeting: 'Hello', sayHi: function (name) {

    } } greeter.sayHi('Jon');
  55. var greeter = { greeting: 'Hello', sayHi: function (name) {

    document.write(this.greeting + ' ' + name) } } greeter.sayHi('Jon');
  56. var greeter = { greeting: 'Hello', sayHi: function (name) {

    document.write(this.greeting + ' ' + name) } } greeter.sayHi('Jon'); // Hello Jon
  57. var greeter = { greeting: 'Hello', sayHi: function (name) {

    document.write(this.greeting + ' ' + name) } } var coolGreeter = { greeting: ‘Whats up', } coolGreeter.sayHi = greeter.sayHi coolGreeter.sayHi(‘Jon');
  58. var greeter = { greeting: 'Hello', sayHi: function (name) {

    document.write(this.greeting + ' ' + name) } } var coolGreeter = { greeting: ‘Whats up', } coolGreeter.sayHi = greeter.sayHi coolGreeter.sayHi('Jon'); // Whats up Jon
  59. var greeter = { greeting: 'Hello', sayHi: function (name) {

    document.write(this.greeting + ' ' + name) } } var coolGreeter = { greeting: ‘Whats up', } var sayHi = greeter.sayHi sayHi('Jon');
  60. var greeter = { greeting: 'Hello', sayHi: function (name) {

    document.write(this.greeting + ' ' + name) } } var coolGreeter = { greeting: ‘Whats up', } var sayHi = greeter.sayHi sayHi('Jon'); // Undefined Jon
  61. var greeter = { greeting: 'Hello', sayHi: function (name) {

    document.write(this.greeting + ' ' + name) } } var coolGreeter = { greeting: ‘Whats up', } var sayHi = greeter.sayHi.bind(greeter) sayHi('Jon');
  62. var greeter = { greeting: 'Hello', sayHi: function (name) {

    document.write(this.greeting + ' ' + name) } } var coolGreeter = { greeting: ‘Whats up', } var sayHi = greeter.sayHi.bind(greeter) sayHi('Jon'); // Hello Jon
  63. var greeter = { greeting: 'Hello', sayHi: function (name) {

    document.write(this.greeting + ' ' + name) } } var coolGreeter = { greeting: ‘Whats up', } var sayHi = greeter.sayHi.bind(coolGreeter) sayHi('Jon');
  64. var greeter = { greeting: 'Hello', sayHi: function (name) {

    document.write(this.greeting + ' ' + name) } } var coolGreeter = { greeting: ‘Whats up', } var sayHi = greeter.sayHi.bind(coolGreeter) sayHi('Jon'); // Whats up Jon
  65. var greeter = { greeting: 'Hello', sayHi: function (name) {

    document.write(this.greeting + ' ' + name) } } var coolGreeter = { greeting: ‘Whats up', } var sayHi = greeter.sayHi sayHi.call(greeter,'Jon');
  66. var greeter = { greeting: 'Hello', sayHi: function (name) {

    document.write(this.greeting + ' ' + name) } } var coolGreeter = { greeting: ‘Whats up', } var sayHi = greeter.sayHi sayHi.call(greeter,'Jon'); // Hello Jon
  67. var greeter = { greeting: 'Hello', sayHi: function (name) {

    document.write(this.greeting + ' ' + name) } } var coolGreeter = { greeting: ‘Whats up', } var sayHi = greeter.sayHi.bind(coolGreeter) sayHi.call(greeter,'Jon');
  68. var greeter = { greeting: 'Hello', sayHi: function (name) {

    document.write(this.greeting + ' ' + name) } } var coolGreeter = { greeting: ‘Whats up', } var sayHi = greeter.sayHi.bind(coolGreeter) sayHi.call(greeter,'Jon'); // Whats up Jon
  69. function Greeter(greeting){ this.greeting = greeting; this.greet = function(name){return this.greeting +

    ' ' + name} this.greetAsync = function(name, cb){ setTimeout(function(){cb(this.greeting + ' ' + name)},0) } } var g = new Greeter('hello'); g.greetAsync('Jon', function(greeting){console.log(greeting)})
  70. function Greeter(greeting){ this.greeting = greeting; this.greet = function(name){return this.greeting +

    ' ' + name} this.greetAsync = function(name, cb){ setTimeout(function(){cb(this.greeting + ' ' + name)},0) } } var g = new Greeter('hello'); g.greetAsync('Jon', function(greeting){console.log(greeting)}) // Undefined Jon
  71. function Greeter(greeting){ this.greeting = greeting; this.greet = function(name){return this.greeting +

    ' ' + name} this.greetAsync = function(name, cb){ setTimeout(function(){cb(this.greeting + ' ' + name)},0) } } var g = new Greeter('hello'); g.greetAsync('Jon', function(greeting){console.log(greeting)}) // Undefined Jon
  72. function Greeter(greeting){ this.greeting = greeting; this.greet = function(name){return this.greeting +

    ' ' + name} this.greetAsync = function(name, cb){ setTimeout(function(){cb(this.greeting + ' ' + name)}.bind(this),0) } } var g = new Greeter('hello'); g.greetAsync('Jon', function(greeting){console.log(greeting)}) // Hello Jon
  73. Arrow Functions

  74. function Greeter(greeting){ this.greeting = greeting; this.greet = function(name){return this.greeting +

    ' ' + name} this.greetAsync = function(name, cb){ setTimeout(()=>{cb(this.greeting + ' ' + name)},0) } } var g = new Greeter('hello'); g.greetAsync('Jon', function(greeting){console.log(greeting)}) // Hello Jon
  75. Prototypes

  76. function Greeter(greeting){ this.greeting = greeting; } Greeter.prototype.greet = function(name){console.log(this.greeting +

    ' ' + name)}; var greeter = new Greeter('Hello'); var coolGreeter = new Greeter('Whats Up');
  77. Greeter.Prototype greet: function(){} coolGreeter greeting: Whats up greeter greeting: Hello

  78. function Greeter(greeting){ this.greeting = greeting; } Greeter.prototype.greet = function(name){console.log(this.greeting +

    ' ' + name)}; var greeter = new Greeter('Hello'); var coolGreeter = new Greeter('Whats Up');
  79. function Greeter(greeting){ this.greeting = greeting; } Greeter.prototype.greet = function(name){console.log(this.greeting +

    ' ' + name)}; var greeter = new Greeter('Hello'); var coolGreeter = new Greeter('Whats Up'); greeter.greet(‘jon’); // Hello Jon coolGreeter.greet(‘jon’); // Whats up Jon
  80. Greeter.Prototype greet: function(){} coolGreeter greeting: Whats up greeter greeting: Hello

  81. function Greeter(greeting){ this.greeting = greeting; } Greeter.prototype.greet = function(name){console.log(this.greeting +

    ' ' + name)}; var greeter = new Greeter('Hello'); var coolGreeter = new Greeter('Whats Up'); greeter.greet(‘jon’); // Hello Jon coolGreeter.greet(‘jon’); // Whats up Jon Greeter.prototype.greet = 2; greeter.greet(‘jon’);
  82. function Greeter(greeting){ this.greeting = greeting; } Greeter.prototype.greet = function(name){console.log(this.greeting +

    ' ' + name)}; var greeter = new Greeter('Hello'); var coolGreeter = new Greeter('Whats Up'); greeter.greet(‘jon’); // Hello Jon coolGreeter.greet(‘jon’); // Whats up Jon Greeter.prototype.greet = 2; greeter.greet(‘jon’); // greeter.greet is not a function
  83. Event Loop

  84. EVENT LOOP CALL STACK EXTERNAL API CALLBACK QUEUE function demo()

    { console.log('Start') setTimeout(() => { console.log('Callback'); }, 100); let sum = 1 + 1; console.log(sum); console.log('End'); }
  85. function demo() { console.log('Start') setTimeout(() => { console.log('Callback'); }, 100);

    let sum = 1 + 1; console.log(sum); console.log('End'); } EVENT LOOP demo() log('Start') CALL STACK EXTERNAL API CALLBACK QUEUE
  86. function demo() { console.log('Start') setTimeout(() => { console.log('Callback'); }, 100);

    let sum = 1 + 1; console.log(sum); console.log('End'); } EVENT LOOP demo() CALL STACK EXTERNAL API CALLBACK QUEUE setTimeout(...)
  87. function demo() { console.log('Start') setTimeout(() => { console.log('Callback'); }, 100);

    let sum = 1 + 1; console.log(sum); console.log('End'); } EVENT LOOP demo() CALL STACK EXTERNAL API 100ms timer CALLBACK QUEUE
  88. function demo() { console.log('Start') setTimeout(() => { console.log('Callback'); }, 100);

    let sum = 1 + 1; console.log(sum); console.log('End'); } EVENT LOOP demo() CALL STACK EXTERNAL API 100ms timer log(2) CALLBACK QUEUE
  89. function demo() { console.log('Start') setTimeout(() => { console.log('Callback'); }, 100);

    let sum = 1 + 1; console.log(sum); console.log('End'); } EVENT LOOP demo() CALL STACK EXTERNAL API log('Callback') CALLBACK QUEUE
  90. function demo() { console.log('Start') setTimeout(() => { console.log('Callback'); }, 100);

    let sum = 1 + 1; console.log(sum); console.log('End'); } EVENT LOOP demo() CALL STACK EXTERNAL API log ('Callback') CALLBACK QUEUE
  91. function demo() { console.log('Start') setTimeout(() => { console.log('Callback'); }, 100);

    let sum = 1 + 1; console.log(sum); console.log('End'); } EVENT LOOP demo() CALL STACK EXTERNAL API CALLBACK QUEUE log ('Callback') log('End')
  92. function demo() { console.log('Start') setTimeout(() => { console.log('Callback'); }, 100);

    let sum = 1 + 1; console.log(sum); console.log('End'); } EVENT LOOP log('Callback') CALL STACK EXTERNAL API CALLBACK QUEUE
  93. function demo() { console.log('Start') setTimeout(() => { console.log('Callback'); }, 100);

    let sum = 1 + 1; console.log(sum); console.log('End'); } EVENT LOOP CALL STACK EXTERNAL API CONSOLE OUTPUT Start 2 End Callback
  94. function demo() { console.log('Start') setTimeout(() => { console.log('Callback'); }, 0);

    let sum = 1 + 1; console.log(sum); console.log('End'); } EVENT LOOP CALL STACK EXTERNAL API CONSOLE OUTPUT Start 2 End Callback
  95. function demo() { console.log('Start') setTimeout(() => { console.log('Callback'); }, 100);

    let result = blockingCode(); console.log(result); console.log('End'); } EVENT LOOP demo() CALL STACK EXTERNAL API 100ms timer blockingCode() CALLBACK QUEUE
  96. EVENT LOOP demo() CALL STACK EXTERNAL API blockingCode() CALLBACK QUEUE

    this blocks callback execution log ('Callback') function demo() { console.log('Start') setTimeout(() => { console.log('Callback'); }, 100); let result = blockingCode(); console.log(result); console.log('End'); }