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

Advanced Topics of JavaScript: Exploring Functions

Advanced Topics of JavaScript: Exploring Functions

Advanced Topics of JavaScript: Exploring Functions

Nizar Khalife Iglesias

February 21, 2016
Tweet

Other Decks in Programming

Transcript

  1. All of its quirks will stay in the language. Don't

    break the Web. This way JavaScript written 15 years ago still works.
  2. When a function is created in JavaScript it is an

    object, just like strings, numbers, arrays, etc. are objects.
  3. You are able to print a function like a regular

    value. function greeting () { console.log("Hello, world!"); } greeting(); console.log(greeting);
  4. Similar to assigning anonymous functions to a variable in PHP.

    // PHP $greeting = function () { echo "Hello, world!\n"; }; $greeting(); var_dump($greeting);
  5. You can assign an anonymous function in JavaScript for the

    same result as before. var greeting = function () { console.log("Hello, world!"); }; greeting(); console.log(greeting);
  6. Function objects are mutable: you can assign properties dynamically. function

    greeting () { console.log("Hello, world!"); greeting.amount += 1; } greeting.amount = 0; greeting(); greeting(); console.log(greeting.amount);
  7. You can even assign functions to properties, creating makeshift methods.

    function greeting () { console.log("Hello, world!"); } greeting.spanish = function () { console.log("Hola, mundo!"); };
  8. Yep, you can call a function on a function. function

    greeting () { console.log("Hello, world!"); } greeting.spanish = function () { console.log("Hola, mundo!"); }; greeting(); greeting.spanish();
  9. Function values you pass into other functions are known as

    callbacks. Run this function when [blank].
  10. Common case for callbacks: adding a click handler in jQuery.

    $(".my-button").click(function () { console.log("You just clicked my button!"); });
  11. You can also pass in a function that's in a

    variable instead of an anonymous function. function doStuff () { console.log("You just clicked my button!"); } // My callback variable // | // v $(".my-button").click( doStuff );
  12. A variable's scope determines what parts of the code it

    can be used in. Scope speaks to the visibility of a variable.
  13. if..else statements and other, non-function {} blocks do not constitute

    a new scope. var pizza = "Pepperonni"; if (true) { var pizza = "Mushroom"; } console.log(pizza); //=> Mushroom
  14. JavaScript has function scope: every function has its own set

    of variables. var pizza = "Pepperonni"; function printPizza () { var pizza = "Mushroom"; console.log(pizza); } printPizza(); //=> Mushroom console.log(pizza); //=> Pepperonni
  15. The key thing to remember about function scope in JavaScript

    is Disney•Pixar. Mnemonics are great for tricky development concepts.
  16. From the inside of printPizza you can see out to

    the variable pizza. var pizza = "Hawaiian"; function printPizza () { console.log(pizza); } printPizza(); //=> Hawaiian
  17. From the outside we do not have access to largePizza.

    function printLargePizza () { var largePizza = "Large Four Cheese"; console.log(largePizza); } printLargePizza(); //=> Large Four Cheese console.log(largePizza); //=> ReferenceError: largePizza is not defined
  18. Practical application of function scope: protect your variables from other

    scripts. (function () { // Other scripts can't see this app variable var app = {}; app.init = function () { console.log("Starting app"); }; app.init(); })();
  19. This is an IFFE (immediately invoked function expression) // No

    name // | // v (function () { // do stuff }) ( ); // ^ // | // Parentheses to // invoke the function You pronounce it like iffy.
  20. Scoping can also be used to make variables private. There's

    no way to make a variable attached to an object private.
  21. The pizza variable is defined inside of doPizzaStuff but used

    inside of printPizza. function doPizzaStuff () { var pizza = "Onion & Garlic"; function printPizza () { console.log(pizza); } printPizza(); } doPizzaStuff(); This works because of inside out.
  22. Functions that use variables that are on the loose are

    known as closures. function doPizzaStuff () { var pizza = "Onion & Garlic"; // Using pizza makes this a closure function printPizza () { console.log(pizza); } printPizza(); } doPizzaStuff(); The printPizza function is a closure.
  23. More often you are returning the closure. function createPizzaPrinter (pizza)

    { // Still a closure function printPizza () { console.log(pizza); } return printPizza; } var onionPrinter = createPizzaPrinter("Onion & Garlic"); onionPrinter();
  24. Practical application of function scope: using closures to make variables

    private. function createCounter () { var count = 0; // Anonymous closure return function () { count += 1; return count; }; } var myCounter = createCounter(); console.log( myCounter() );
  25. Function context is represented by the magical keyword this. function

    printPizza () { var pizza = "Fancy Arugula"; console.log(pizza, this); // ^ // | // Magically defined in every function }
  26. this is magical because it changes depending one how the

    function is invoked. It can potentially have different, unexpected values.
  27. When you call the function in the regular way this

    is the global object, window. function printPizza () { var pizza = "Fancy Arugula"; console.log(pizza, this); // ^ // | // window } printPizza(); //=> Fancy Arugula, Window {}
  28. All global variables and functions are properties of window. console.log(

    window ); //=> Window { // Array: function Array(), // Number: function Number(), // Object: function Object(), // RegExp: function RegExp(), // console: Console, // document: document, // setTimeout: function setTimeout(), // undefined: undefined, // ... etc. // }
  29. The other way main way to call functions is as

    methods of an object Let's take a look at a simple pizza object.
  30. Our pizza has toppings and cheese attributes. var pizza =

    { toppings: "Fancy Arugula", cheese: "Mozzarella" }; console.log( pizza.toppings ); //=> Fancy Arugula console.log( pizza.cheese ); //=> Mozzarella
  31. Let's add a print method. var pizza = { toppings:

    "Fancy Arugula", cheese: "Mozzarella" }; pizza.print = function () { // print pizza stuff };
  32. When you call a function as the method of an

    object, this is the object. var pizza = { toppings: "Fancy Arugula", cheese: "Mozzarella" }; pizza.print = function () { console.log(this.toppings + " and " + this.cheese + " Pizza"); // ^ ^ // | | // pizza.toppings pizza.cheese }; pizza.print(); //=> Fancy Arugula and Mozzarella Pizza
  33. If you assign the method to a variable and call

    it, this is window. var pizza = { toppings: "Fancy Arugula", cheese: "Mozzarella" }; pizza.print = function () { console.log(this.toppings + " and " + this.cheese + " Pizza"); // ^ ^ // | | // window.toppings window.cheese }; var printPizza = pizza.print; printPizza(); //=> undefined and undefined Pizza
  34. You can set the context explicitly with .call(). var pizza

    = { toppings: "Fancy Arugula", cheese: "Mozzarella" }; pizza.print = function () { console.log(this.toppings + " and " + this.cheese + " Pizza"); }; var printPizza = pizza.print; printPizza.call( pizza ); //=> Fancy Arugula and Mozzarella Pizza
  35. You have to do this every time you want to

    execute the function. var pizza = { toppings: "Fancy Arugula", cheese: "Mozzarella" }; pizza.print = function () { console.log(this.toppings + " and " + this.cheese + " Pizza"); }; var printPizza = pizza.print; printPizza.call(pizza); printPizza.call(pizza);
  36. But you can pass in different contexts on the fly

    var pizza = { toppings: "Fancy Arugula", cheese: "Mozzarella" }; var otherPizza = { toppings: "Bison", cheese: "Cheddar" }; pizza.print = function () { console.log(this.toppings + " and " + this.cheese + " Pizza"); }; var printPizza = pizza.print; printPizza.call( pizza ); //=> Fancy Arugula and Mozzarella Pizza printPizza.call( otherPizza ); //=> Bison and Cheddar Pizza
  37. The .apply() method works in a similar way. var pizza

    = { toppings: "Fancy Arugula", cheese: "Mozzarella" }; var otherPizza = { toppings: "Bison", cheese: "Cheddar" }; pizza.print = function () { console.log(this.toppings + " and " + this.cheese + " Pizza"); }; var printPizza = pizza.print; printPizza.apply( pizza ); //=> Fancy Arugula and Mozzarella Pizza printPizza.apply( otherPizza ); //=> Bison and Cheddar Pizza
  38. You can also set context of a function with .bind().

    var pizza = { toppings: "Fancy Arugula", cheese: "Mozzarella" }; pizza.print = function () { console.log(this.toppings + " and " + this.cheese + " Pizza"); }; var printPizza = pizza.print.bind( pizza ); // ^ // | // Bound to pizza printPizza(); //=> Fancy Arugula and Mozzarella Pizza
  39. .bind() really creates a new function with a fixed context.

    var pizza = { toppings: "Fancy Arugula", cheese: "Mozzarella" }; pizza.print = function () { console.log(this.toppings + " and " + this.cheese + " Pizza"); }; var printPizza = pizza.print.bind( pizza ); console.log( printPizza === pizza.print ); //=> false
  40. The new function is immune to further context changes. var

    pizza = { toppings: "Fancy Arugula", cheese: "Mozzarella" }; var otherPizza = { toppings: "Bison", cheese: "Cheddar" }; pizza.print = function () { console.log(this.toppings + " and " + this.cheese + " Pizza"); }; var printPizza = pizza.print.bind( pizza ); printPizza(); //=> Fancy Arugula and Mozzarella Pizza printPizza.call( otherPizza ); //=> Fancy Arugula and Mozzarella Pizza
  41. Practical application of this and context: callback functions' this will

    always be window. var pizza = { toppings: "Fancy Arugula", cheese: "Mozzarella" }; pizza.print = function () { console.log(this.toppings + " and " + this.cheese + " Pizza"); }; setTimeout( pizza.print, 3000 ); // After 3 seconds //=> undefined and undefined Pizza
  42. Bind the method var pizza = { toppings: "Fancy Arugula",

    cheese: "Mozzarella" }; pizza.print = function () { console.log(this.toppings + " and " + this.cheese + " Pizza"); }; setTimeout( pizza.print.bind(pizza), 3000 ); // After 3 seconds //=> Fancy Arugula and Mozzarella Pizza
  43. Use a closure var pizza = { toppings: "Fancy Arugula",

    cheese: "Mozzarella" }; pizza.print = function () { console.log(this.toppings + " and " + this.cheese + " Pizza"); }; function printPizza () { pizza.print(); } setTimeout( printPizza, 3000 ); // After 3 seconds //=> Fancy Arugula and Mozzarella Pizza
  44. About me Anyway... I've been Nizar Khalife Iglesias. You can

    follow me pretty much everywhere @khalifenizar.