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. typeof undefined // "undefined" typeof 0 // "number" typeof true

    // "boolean" typeof “PrDC” // "string"
  3. 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)
  4. var myVariable = 10; function func(){ myVariable = 25; var

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

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

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

    myVariable is not defined let myVariable; console.log(myVariable); } func(); console.log(myVariable);
  8. function getGreeter(){ var greeting = 'Hello' return { greeter: function(name){console.log(greeting

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

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

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

    + ' ' + name)} } } var g = getGreeter(); var x = g.greeter; x(‘Jon'); // Hello Jon
  12. var greeter = { greeting: 'Hello', sayHi: function (name) {

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

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

    document.write(this.greeting + ' ' + name) } } var coolGreeter = { greeting: ‘Whats up', } coolGreeter.sayHi = greeter.sayHi coolGreeter.sayHi(‘Jon');
  15. 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
  16. var greeter = { greeting: 'Hello', sayHi: function (name) {

    document.write(this.greeting + ' ' + name) } } var coolGreeter = { greeting: ‘Whats up', } var sayHi = greeter.sayHi sayHi('Jon');
  17. 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
  18. 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');
  19. 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
  20. 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');
  21. 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
  22. 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');
  23. 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
  24. 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');
  25. 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
  26. 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)})
  27. 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
  28. 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
  29. 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
  30. 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
  31. 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');
  32. 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');
  33. 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
  34. 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’);
  35. 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
  36. 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'); }
  37. 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
  38. 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(...)
  39. 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
  40. 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
  41. 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
  42. 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
  43. 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')
  44. 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
  45. 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
  46. 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
  47. 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
  48. 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'); }