Slide 1

Slide 1 text

Advanced Topics of JavaScript: Exploring Functions by Nizar Khalife @khalifenizar

Slide 2

Slide 2 text

Please interrupt me with questions!

Slide 3

Slide 3 text

The wild world of functions Part 1 of 5 ••••

Slide 4

Slide 4 text

JavaScript is a bit nutty. And it will remain so.

Slide 5

Slide 5 text

All of its quirks will stay in the language. Don't break the Web. This way JavaScript written 15 years ago still works.

Slide 6

Slide 6 text

It's especially eccentric with functions Functions are the most important thing in JavaScript.

Slide 7

Slide 7 text

Let's address some of those function gotchas that commonly throw off new JavaScript developers.

Slide 8

Slide 8 text

Functions are values Part 2 of 5 ••••

Slide 9

Slide 9 text

In JavaScript, functions are values. That's the first weird thing.

Slide 10

Slide 10 text

You might have heard the phrase "functions are first class citizens" in JavaScript.

Slide 11

Slide 11 text

When a function is created in JavaScript it is an object, just like strings, numbers, arrays, etc. are objects.

Slide 12

Slide 12 text

You are able to print a function like a regular value. function greeting () { console.log("Hello, world!"); } greeting(); console.log(greeting);

Slide 13

Slide 13 text

Similar to assigning anonymous functions to a variable in PHP. // PHP $greeting = function () { echo "Hello, world!\n"; }; $greeting(); var_dump($greeting);

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

You can even assign functions to properties, creating makeshift methods. function greeting () { console.log("Hello, world!"); } greeting.spanish = function () { console.log("Hola, mundo!"); };

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

Practical application of functions being values: functions as arguments to other functions.

Slide 19

Slide 19 text

Function values you pass into other functions are known as callbacks. Run this function when [blank].

Slide 20

Slide 20 text

Common case for callbacks: adding a click handler in jQuery. $(".my-button").click(function () { console.log("You just clicked my button!"); });

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

Function scope & closures Part 3 of 5 ••••

Slide 23

Slide 23 text

Local variables in JavaScript have a specific scope. Local variables are those created with var.

Slide 24

Slide 24 text

A variable's scope determines what parts of the code it can be used in. Scope speaks to the visibility of a variable.

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

The key thing to remember about function scope in JavaScript is Disney•Pixar. Mnemonics are great for tricky development concepts.

Slide 28

Slide 28 text

Variables can be seen from the inside out. But not from the outside in.

Slide 29

Slide 29 text

From the inside of printPizza you can see out to the variable pizza. var pizza = "Hawaiian"; function printPizza () { console.log(pizza); } printPizza(); //=> Hawaiian

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

This is an IFFE (immediately invoked function expression) // No name // | // v (function () { // do stuff }) ( ); // ^ // | // Parentheses to // invoke the function You pronounce it like iffy.

Slide 33

Slide 33 text

Scoping can also be used to make variables private. There's no way to make a variable attached to an object private.

Slide 34

Slide 34 text

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.

Slide 35

Slide 35 text

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.

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

Function context & this Part 4 of 5 ••••

Slide 39

Slide 39 text

Functions also have a context, an object that owns the call to the function.

Slide 40

Slide 40 text

Function context is represented by the magical keyword this. function printPizza () { var pizza = "Fancy Arugula"; console.log(pizza, this); // ^ // | // Magically defined in every function }

Slide 41

Slide 41 text

this is magical because it changes depending one how the function is invoked. It can potentially have different, unexpected values.

Slide 42

Slide 42 text

The manner of execution determines the rules for the context.

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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. // }

Slide 45

Slide 45 text

The other way main way to call functions is as methods of an object Let's take a look at a simple pizza object.

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

Here's where it gets complicated... Incoming mind blow!

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

.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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

setTimeout pseudo code function setTimeout (callback, ms) { // Wait ms milliseconds callback(); }

Slide 60

Slide 60 text

So how do we get around callbacks and context? A couple of techniques.

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

Resources & exercises Part 5 of 5 ••••

Slide 64

Slide 64 text

bit.ly/exploring-js-functions Bunch of links on this URL.

Slide 65

Slide 65 text

bit.ly/exploring-js-functions NodeSchool Interactive JavaScript tutorials on your terminal.

Slide 66

Slide 66 text

bit.ly/exploring-js-functions Mozilla Developer Network In-depth articles on all these things.

Slide 67

Slide 67 text

bit.ly/exploring-js-functions Effective JavaScript A great book on all the nuances of JavaScript.

Slide 68

Slide 68 text

About me Anyway... I've been Nizar Khalife Iglesias. You can follow me pretty much everywhere @khalifenizar.

Slide 69

Slide 69 text

About me I work as the Lead Instructor at Ironhack.

Slide 70

Slide 70 text

No content

Slide 71

Slide 71 text

We are looking for mentors to help our students in their journey.

Slide 72

Slide 72 text

Being a mentor is a 4 hour commitment across 2 weeks.

Slide 73

Slide 73 text

If you want to pay it forward talk to me and apply.

Slide 74

Slide 74 text

Advanced Topics of JavaScript: Exploring Functions bit.ly/exploring-js-functions @khalifenizar