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

    View Slide

  2. View Slide

  3. View Slide

  4. View Slide

  5. View Slide

  6. Types

    View Slide

  7. Types
    NUMBER
    STRING
    BOOLEAN
    NULL
    UNDEFINED
    FUNCTION
    OBJECT
    SYMBOL

    View Slide

  8. typeof undefined // "undefined"
    typeof 0 // "number"
    typeof true // "boolean"
    typeof “PrDC” // "string"

    View Slide

  9. typeof null

    View Slide

  10. typeof null // object

    View Slide

  11. typeof NaN

    View Slide

  12. typeof NaN // number

    View Slide

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

    View Slide

  14. console.log(1 + 1);

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  18. console.log(42 + true);

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  25. Hoisting

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  30. console.log(myVariable);

    View Slide

  31. ReferenceError: myVariable is not defined
    at Object. (/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)

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  41. Functions

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  49. Closures

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  53. This

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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');

    View Slide

  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

    View Slide

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

    View Slide

  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

    View Slide

  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');

    View Slide

  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

    View Slide

  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');

    View Slide

  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

    View Slide

  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');

    View Slide

  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

    View Slide

  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');

    View Slide

  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

    View Slide

  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)})

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  73. Arrow Functions

    View Slide

  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

    View Slide

  75. Prototypes

    View Slide

  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');

    View Slide

  77. Greeter.Prototype
    greet: function(){}
    coolGreeter
    greeting: Whats up
    greeter
    greeting: Hello

    View Slide

  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');

    View Slide

  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

    View Slide

  80. Greeter.Prototype
    greet: function(){}
    coolGreeter
    greeting: Whats up
    greeter
    greeting: Hello

    View Slide

  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’);

    View Slide

  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

    View Slide

  83. Event Loop

    View Slide

  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');
    }

    View Slide

  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

    View Slide

  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(...)

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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')

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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');
    }

    View Slide