#Lesson 4 - Functions - Part 2 - Scopes, Closures, & this
- Over the past 3 lessons, we've seen all the major building blocks of JS
- variables
- arrays
- objects
- the basics of functions
- Tonight we'll be covering the more advanced parts of functions
- Scope
- Closures
- this
What are functions?
- A function is a reusable piece of code that performs a task
- A function is an object, just like objects and arrays
- A function and its return value are not the same thing.
- Defining a function requires PBR (Parameters, body, return value)
- Parameters - What input does the function need in order to run?
- Body - What will the function do with that information?
- Return - What output will executing the function give back?
function nameOfMyFunction(list, of, parameters) {
//BODY: Logic and operations based on parameters e.g.
//RETURN: Value returned to the caller of the function;
return list;
}
nameOfMyFunction(1,2,3); // 1- Scope is the set of variables a piece of code has access to.
- Only functions create scope
- Parameters and variables declared inside a function are LOCAL to that function's scope
- Variables are only visible inside that scope they are defined in and in its child scopes
So, what is a lexical scope? Lexical scoping simply means that variables refer to their local environment.
function add() {
var a = "This variable is only visible inside the add function";
}
console.log(a) // Undefinedfunction getGreeting(name) {
var greeting = "hello ";
return greeting + name;
}
getGreeting('Shane'); // 'Hello Shane'
console.log(greeting) //undefinedBlocks DO NOT have their own scope
for(var i = 0; i < 10; i++) {
var x = i;
}
console.log(i,x); //9,9Scope lets you create private variables in a JS program, but be careful, variables defined without the 'var' keyword are global.
function greet(name) {
greeting = "hello ";
return greeting + name
}
greet('Shane');
greeting //'hello'!- When a scope is created, it is nested inside another scope.
- To resolve a variable, JS looks at the immediate scope, then parent scopes in order.
- A closure is an inner function that has access to the outer function’s variables. Both scopes together are the scope chain.
For example, the city variable is visible inside the greet function because the greet function creates a closure.
var city = 'Charlotte';
var greet = function() {
console.log('Hello ' + city);
}
greet(); // Hello CharlotteAccessing city inside the greet function will first look for a variable named city in the greet function, then to the parent scope, and so on up the scope chain.
function outer() {
var x = 'x';
function inner() {
var y = 'y';
console.log(x); //'x'
}
console.log(x); // 'x'
console.log(y); // ReferenceError: y is not defined
}var landscape = function() {
var result = "";
var flat = function(size) {
for (var count = 0; count < size; count++)
result += " _ ";
};
var mountain = function(size) {
result += "/";
for (var count = 0; count < size; count++)
result += " '";
result += "\\";
};
flat(3);
mountain(4);
flat(6);
mountain(1);
flat(1);
return result;
};
console.log(landscape());flatandmountainare functions only available withinlandscape- The
resultvariable is available insideflatandmountainbecause
Sometimes parent scopes have variables with the same name.
var name = 'Shane';
var greet = function() {
var name = 'Matt'
console.log(name);
}
console.log(name); // Shane
console.log(greet(name)); // MattDeclaring the variable name in the inner scope hides the variable with the same name in the outer scope. This is a new variable, so assigning to the inner variable won't affect the outer.
Sometimes a function defines argument names with the same name as variables in the parent scope. This works the same way as the example above.
var name = 'Shane';
var greet = function(name) {
console.log(name);
}
greet('joe'); // 'joe'
//equivalant to
var name = 'Shane';
var greet = function(mySuperUniqueVariableName) {
var name = mySuperUniqueVariableName;
console.log(name);
}
greet('joe'); // 'joe'
Start with the following code template. After each step, run the program and see how the output changes.
function outer(){
function inner() {
}
inner();
}
outer();- Declare two variables,
aandbin the outer function's scope and set them to a string and an object respectively. Log their values immediately. - Log the values of
aandbin the inner function. - Update the inner function to take two parameters named
aandb. - Pass
aandbin as arguments when you execute inner(). - Inside the inner function, assign new values to
aandband log them at the end of the function AND after the execution ofinner(a,b). - Inside the inner function, update a property of the
bobject.
- A Function has access to the variables that were in scope when it was defined, not executed.
- Sorry, this next example is just evil...
//Scope, closure, and hoisting, oh my!
function createFunction() {
var a = "Hans Zimmer Rules!";
inception = function() {
console.log(a);
}
}
var inception;
createFunction();
inception(); // "Hans Zimmer Rules!"Inside a function, the keyword this refers to the executor of the function.
- PAPER EXERCISE
Again, think of a function as a piece of paper with instructions, a procedure of sorts. One of those instructions might say "touch your nose". But who is this "you" it speaks of? Obviously, the person executing the instructions. Similarly, the keyword 'this' refers to the object that's executing the function.
var teacher = {
name: 'Assaf',
sayName: function() {
console.log(this.name);
}
}
teacher.sayName(); //'Assaf'Different objects can execute the same function, can produce different results because this is different.
function sayName() {
console.log(this.name);
}
var teacher1 = {
name: 'Assaf',
speak: sayName
}
var teacher2 = {
name: 'Shane',
speak: sayName
}
teacher1.speak(); // 'Assaf'
teacher2.speak(); // 'Shane'Create a single object named slideshow that represents the data and functionality of a picture slideshow. There should be NO VARIABLES OUTSIDE THE OBJECT. The object should have properties for:
- An array called
photoListthat contains the names of the photos as strings - An integer
currentPhotoIndexthat represents which photo in thephotoListis currently displayed - A
nextPhoto()function that movescurrentPhotoIndexto the next indexifthere is one, and: 4. logs the current photo name. 4. Otherwise, log "End of slideshow"; - A
prevPhoto()function that does the same thing, but backwards. - A function
getCurrentPhoto()that returns the current photo from the list.
// Have fun :)###Due 8/2/16:
-
Complete the Scope Chain & Closures Module at NodeSchool
- Upload a completed screenshot to slack
-
Complete the Slideshow challenge
- Push the finished code to GitHub using the naming convetion:
slideshow_YOUR_TEAM_INTIALS_HERE - Paste a link to the finished code in Slack
- Push the finished code to GitHub using the naming convetion:
-
Read this article on Scope and Closure
-
Read the You Don't Know JS book on closures. (chapters 1 - 5)
- Complete the code examples
- push to github with the name: YDKJS_closures_YOUR_INITIALS_HERE
-
Watch this TeamTreehouse video on scope

