What's hoisting? →
What are some hoisting rules? →
let
and const
declarations are sort of hoisted (their names are created, but they can't be used until they're actually declared)var
declarations are brought to the top of the scopevar
variables are undefined
)What is the output of the following code? Error or no output are possible. →
console.log(x);
ReferenceError: x is not defined
(x wasn't declared yet)
What is the output of the following code? Error or no output are possible. →
let x;
console.log(x);
undefined
let
variables are initialized to undefined
console.log(x);
let x;
ReferenceError
Temporal Dead Zone - can't access let
variable before actual declaration
console.log(x);
var x;
undefined
the var
declaration for x is hoisted
What is the output of the following code? Error or no output are possible. →
f(5);
var f = function(x) {
console.log(x);
}
TypeError: undefined is not a function
variable declaration is hoisted, but the initialization of its value is not…. the value, undefined
is being used as a function!?
What is the output of the following code? Error or no output are possible. →
f(5);
function f(x) {
console.log(x);
}
5
when using function declaration syntax, both declaration and actual definition of function are hoisted
var
A quick summary on using var →
var
(and don't have a const
or let
either), the declaration is not hoistedvar
will create a local variable … and the scope of it will be that functionconst
, let
or var
, the interpreter will look up the scope chain until it finds that variable or hits the global scope (at which point it will create it)const
, let
or var
What's the output of this code? →
let g = 7;
function f() {
g = 5;
}
f();
console.log(g);
// the variable, g, within the function, f...
// changes the global variable, g
5
What's the output of this code? →
let g = 7;
function f() {
g = 5;
function g() {}
}
f();
console.log(g);
7 (!?)
This illustrates going up the scope chain… what's the output? →
let x = 10;
function f() {
function g() {
x = 20;
}
g();
}
console.log(x);
f();
console.log(x);
10 // global
20 // nearest x is global, so global is changed by x = 20
A minor change in code…. (declaring a local in f). What's the output this time? →
let x = 10;
function f() {
let x = 30;
function g() {
x = 20;
}
g();
}
f();
console.log(x);
// nearest x is in f, so global x is not changed
10
You can pass as many or as few arguments to functions as you like!
Wait… what!? →
undefined
arguments
variable added to the function's context (along with a this variable) … maybe we'll check these out later
Let's check this out →
Given the following function…
function f(a, b) {
console.log(a, b);
}
What is output of this function if called with the following arguments? →
f(1, 2);
f(1);
f();
1 2
1 undefined
undefined undefined
Using the following syntax for rest parameters … you can create functions that have an indefinite number of arguments represented as a real Array mixed in with initial positional arguments →
function hiEveryone(greeting, ...names) {
console.log(greeting);
console.log(names);
}
hiEveryone('Hello', 'Alice', 'Bob', 'Carol')
Hello
[ 'Alice', 'Bob', 'Carol' ]
names
is an actual Array
, so you can use Array
methods on it (unlike the arguments
object, which is a fake Array-like object)
When a function is called, it gets an arguments object in its context, along with its defined parameters (and this, but we'll talk about that later). Let's see this in action. →
const f = function() {
console.log("number of args " + arguments.length);
for (let i = 0, j = arguments.length; i < j; i++) {
console.log(arguments[i]);
}
};
f(1, 2, 3);
The arguments object is array-like, but not an array. (Let's see. →)
for
loop)slice
, pop
, forEach
, etc.)Create a function called mySum
that takes an arbitrary number of numbers as separate arguments and returns the sum of all of the arguments
console.log(mySum(1, 2, 3)); // --> 6
var mySum = function() {
var total = 0;
for(var i = 0; i < arguments.length; i++) {
total += arguments[i];
}
return total;
}
Both arguments
and rest parameters allow for an arbitrary number of arguments. Which should be used? &arr;
Array
Array
What operator could we use to give parameters default values if they're not passed in? →
For example, how would we create a function called greetTheWorld
greeting
greeting
, followed by "world"
greetTheWorld("Hi")
→ Hi world!
"Hello"
greetTheWorld()
→ Hello world!
Let's see an implementation in the next slide. →
We can use the ||
operator to give a default value if the value on the left is false-y:
function greetTheWorld(greeting) {
console.log((greeting || "Hello") + " world!");
}
You can also add default values directly in the function header in ES6 →
function f(x=1) {
console.log(x);
}
f(); // no args, result is 1!
These values are evaluated at call time, so a new object is created each time (that way, changes won't be persisted across function calls for default arguments that are mutable) →
function extraSauce(condiments = []) {
condiments.push('ketchup');
console.log(condiments);
}
extraSauce() // ['ketchup']
extraSauce() // still just ['ketchup']
You can even reference other parameters in your expression!
function foo(a = 1, b = (2 * a)) {
console.log(a, b);
}
foo(); // 1 2
foo(7); // 7 14
Parameters with default values can be anywhere in parameter list →
function foo(a, b = 'it me!', c) {
console.log(a, b, c);
}
foo(1, 2, 3) // 1 2 3
foo(1) // 1 'it me!' undefined
The value, undefined
, is what actually triggers the default value
foo(1, undefined, 3) // 1 it me! 3
Functions retain access to their original scope, even when the outer function they were defined in has returned. What happens here? →
let gimmeFunction = function() {
let a = "I'm in here!";
return function() {
console.log(a);
}
}
let myFunction = gimmeFunction();
myFunction();
I'm in here!
(Via MDN)…
gimmeFunction
finishes executing, you'd expect that its local letiable, a, would no longer be accessibleTry writing a function called makeAdder
: →
It should look like this:
let addTwo = makeAdder(2);
console.log(addTwo(5));
// should print out 7
Here's a possible solution: →
let makeAdder = function(x) {
return function(y) {
return y + x;
}
};
let addTwo = makeAdder(2);
console.log(addTwo(5));