WDIM387 Week 2
JavaScript functions
Instructor: Dan Muzyka
danmuzyka.ai@gmail.com
Operators (Review from last week)
Conditional Statements
if (porridge === 'too hot') {
spitOut();
}
else if (porridge === 'too cold') {
pourDownDrain();
}
// Else porridge is 'just right'
else {
devour();
}
Conditional Statements
switch (porridge) {
case 'too hot':
spitOut();
break;
case 'too cold':
pourDownDrain();
break;
// Otherwise, assume 'just right'
default:
devour();
break;
}
Conditional Statements
switch (porridge) {
// If too hot or too cold, both spit out and pour down drain.
case 'too hot':
case 'too cold':
spitOut();
pourDownDrain();
break;
// Otherwise, assume 'just right'
default:
devour();
break;
}
Loops
var bowlsOfPorridge = [hotBowl, coldBowl, justRightBowl];
for (var i = 0; i < bowlsOfPorridge.length; i++) {
taste(bowlsOfPorridge[i]);
}
Loops
var bowlsOfPorridge = [hotBowl, coldBowl, justRightBowl];
for (var i = 0, numBowls = bowlsOfPorridge.length; i < numBowls; i++) {
taste(bowlsOfPorridge[i]);
}
Loops
var bowlsOfPorridge = [hotBowl, coldBowl, justRightBowl];
for (var i = bowlsOfPorridge.length; i--;) {
taste(bowlsOfPorridge[i]);
}
What is happening here? What are the benefits? What are the drawbacks?
Loops
var bowlsOfPorridge = [hotBowl, coldBowl, justRightBowl],
i = bowlsOfPorridge.length - 1;
do {
taste(bowlsOfPorridge[i]);
i--;
} while (i >= 0);
Loops
var isPorridgeTasty = function(bowl) {
return (bowl === 'just right bowl');
};
var bowlsOfPorridge = ['hot bowl', 'cold bowl', 'just right bowl'],
yummyPorridge = false,
i = bowlsOfPorridge.length - 1;
do {
yummyPorridge = isPorridgeTasty(bowlsOfPorridge[i]);
if (yummyPorridge) {
console.log(bowlsOfPorridge[i]);
}
i--;
} while (i >= 0);
Loops
What's wrong with this version?
var isPorridgeTasty = function(bowl) {
return (bowl === 'just right bowl');
};
var bowlsOfPorridge = ['hot bowl', 'cold bowl', 'just right bowl'],
yummyPorridge = false,
i = bowlsOfPorridge.length - 1;
do {
yummyPorridge = isPorridgeTasty(bowlsOfPorridge[i]);
if (yummyPorridge) {
console.log(bowlsOfPorridge[i]);
}
i--;
} while (!yummyPorridge);
Loops
What difference does a while loop make versus do-while?
var isPorridgeTasty = function(bowl) {
return (bowl === 'just right bowl');
};
var bowlsOfPorridge = ['hot bowl', 'cold bowl', 'just right bowl'],
yummyPorridge = false,
i = bowlsOfPorridge.length - 1;
while (i >= 0) {
yummyPorridge = isPorridgeTasty(bowlsOfPorridge[i]);
if (yummyPorridge) {
console.log(bowlsOfPorridge[i]);
}
i--;
}
Break
var isPorridgeTasty = function(bowl) {
return (bowl === 'just right bowl');
};
var bowlsOfPorridge = ['scalding bowl', 'moldy bowl', 'just right bowl', 'poisoned bowl', 'hot bowl', 'cold bowl', 'stinky bowl'],
yummyPorridge = false,
numBowls = bowlsOfPorridge.length,
i = 0;
while (i < numBowls) {
yummyPorridge = isPorridgeTasty(bowlsOfPorridge[i]);
console.log("Tasted " + bowlsOfPorridge[i]);
if (yummyPorridge) {
console.log("There is at least one bowl of yummy porridge on this table!");
break;
}
i++;
}
Break
var isPorridgeTasty = function(bowl) {
return (bowl === 'just right bowl');
};
var firstTableBowlsOfPorridge = ['scalding bowl', 'moldy bowl', 'just right bowl', 'poisoned bowl'],
secondTableBowlsOfPorridge = ['hot bowl', 'cold bowl', 'stinky bowl', 'just right bowl'],
tables = [firstTableBowlsOfPorridge, secondTableBowlsOfPorridge];
yummyPorridge = false,
numTables = tables.length,
i = 0;
checkTables: while (i < numTables) {
var j = 0, numBowls = tables[i].length;
checkBowls: while (j < numBowls) {
yummyPorridge = isPorridgeTasty(tables[i][j]);
console.log("Tasted " + tables[i][j]);
if (yummyPorridge) {
console.log("There is at least one bowl of yummy porridge on table " + (i + 1) + "!"); // Why do we wrap i + 1 in parentheses?
break checkBowls;
}
j++;
}
i++;
}
Continue
var isPorridgeTasty = function(bowl) {
return (bowl === 'just right bowl');
};
var firstTableBowlsOfPorridge = ['scalding bowl', 'moldy bowl', 'just right bowl', 'poisoned bowl'],
secondTableBowlsOfPorridge = ['hot bowl', 'cold bowl', 'stinky bowl', 'just right bowl'],
tables = [firstTableBowlsOfPorridge, secondTableBowlsOfPorridge];
yummyPorridge = false,
numTables = tables.length,
i = 0;
checkTables: while (i < numTables) {
var j = 0, numBowls = tables[i].length;
checkBowls: while (j < numBowls) {
yummyPorridge = isPorridgeTasty(tables[i][j]);
console.log("Tasted " + tables[i][j]);
if (yummyPorridge) {
console.log("There is at least one bowl of yummy porridge on table " + (i + 1) + "!");
i++; // Why is this line necessary?
continue checkTables;
}
j++;
}
i++;
}
Break
(The other kind)
Functions
Functions provide variable scope.
var isPorridgeTasty = function(bowl) {
console.log(bowl); // Works fine
return (bowl === 'just right bowl');
};
isPorridgeTasty('frozen bowl');
console.log(bowl); // Causes ReferenceError
Functions
Variables are hoisted within functions. In other words, they are treated as if they were declared at the beginning of the function, but not with values assigned.
var breakIntoHouse = function() {
var task1 = "eat porridge";
console.log(task1); // "eat porridge"
console.log(task2); // undefined
console.log(task3); // ReferenceError
var task2 = "ruin chairs";
return task1 + ", then " + task2;
}
breakIntoHouse();
Functions
// This version:
var breakIntoHouse = function() {
var task1 = "eat porridge";
console.log(task1); // "eat porridge"
console.log(task2); // undefined
var task2 = "ruin chairs";
return task1 + ", then " + task2;
}
breakIntoHouse();
// ...is equivalent to this version:
var breakIntoOtherHouse = function() {
var task1 = "eat porridge", task2;
console.log(task1); // "eat porridge"
console.log(task2); // undefined
task2 = "ruin chairs";
return task1 + ", then " + task2;
}
breakIntoOtherHouse();
Functions
To reduce confusion, declare all variables at top of function.
var breakIntoHouse = function() {
var task1 = "eat porridge", task2 = "ruin chairs";
console.log(task1);
console.log(task2);
return task1 + ", then " + task2;
}
breakIntoHouse();
Functions
Functions are first-class objects.
- Can be assigned to variables.
- Can be passed as arguments to other functions.
- Can be returned from other functions.
- Can have their own properties and methods.
Functions
Functions can be assigned to variables.
var isPorridgeTasty = function(bowl) {
return (bowl === 'just right bowl');
};
Functions
You can define a function using a "function declaration" or a "function expression."
// Function declaration
function isPorridgeTasty(bowl) {
return (bowl === 'just right bowl');
}
// Function expression (anonymous function)
var isPorridgeTasty = function(bowl) {
return (bowl === 'just right bowl');
};
// Named function expression
var isPorridgeTasty = function isPorridgeTasty(bowl) {
return (bowl === 'just right bowl');
};
Functions
// You can bind a function to a variable name that is different
// from the function name.
var isPorridgeTasty = function doILikeThePorridge(bowl) {
return (bowl === 'just right bowl');
};console.log(isPorridgeTasty('icky bowl')); // false
console.log(doILikeThePorridge('nasty bowl')); // ReferenceError
Functions
Named function expressions are often used for debugging.
var isPorridgeTasty = function doILikeThePorridge(bowl) {
console.log(isPorridgeTasty.name); // doILikeThePorridge
console.log(doILikeThePorridge.name); // doILikeThePorridge
return (bowl === 'just right bowl');
};
isPorridgeTasty('icky bowl');
console.log(isPorridgeTasty.name); // doILikeThePorridge
console.log(doILikeThePorridge.name) // ReferenceError
Functions
Functions can be passed as arguments to other functions.
var bowls = [
{name: "cold porridge", empty: false},
{name: "hot porridge", empty: false},
{name: "just right porridge", empty: false}
],
chairs = [
{name: "hard chair", broken: false},
{name: "soft chair", broken: false},
{name: "just right chair", broken: false}
],
houseContents = {"bowls": bowls, "chairs": chairs};
var breakIntoHouse = function() {
var houseContents = arguments[0],
numCallbacks = arguments.length - 1,
i = 1;
for (i; i <= numCallbacks; i++) {
if (typeof arguments[i] === "function") {
arguments[i](houseContents);
}
}
};
var eatPorridge = function(houseContents) {
if (typeof houseContents.bowls === "object") {
for (i in houseContents.bowls) {
houseContents.bowls[i].empty = true;
}
}
}
breakIntoHouse(houseContents, eatPorridge);
console.log(houseContents);
Functions
What are some examples of callbacks you have seen in your experience with JavaScript?
Functions
Functions can return other functions. This situation can result in closures.
var wreakHavoc = function(verb, directObject) {
var i = 1,
havoc = function() {
var j = i;
i++;
return "Goldilocks " + verb + " " + j + " " + directObject;
};
return havoc;
}
var stealPorridge = wreakHavoc("devoured", "bowls of porridge");
// variable i persists from one invocation to the next
console.log(stealPorridge()); // Goldilocks devoured 1 bowls of porridge
console.log(stealPorridge()); // Goldilocks devoured 2 bowls of porridge
console.log(stealPorridge()); // Goldilocks devoured 3 bowls of porridge
Functions
var wreakHavoc = function(verb, directObject) {
var i = 1,
havoc = function() {
var j = i;
i++;
return "Goldilocks " + verb + " " + j + " " + directObject;
};
return havoc;
}
var stealPorridge = wreakHavoc("devoured", "bowls of porridge");
console.log(stealPorridge()); // Goldilocks devoured 1 bowls of porridge
console.log(stealPorridge()); // Goldilocks devoured 2 bowls of porridge
console.log(stealPorridge()); // Goldilocks devoured 3 bowls of porridge
var breakChairs = wreakHavoc("smashed", "chairs");
// What will these return?
console.log(breakChairs());
console.log(breakChairs());
Break
Hoisting Review
Closures Review
Read "How do JavaScript closures work?" and, individually or in small groups, create your own examples of closures. Present your examples to the rest of the class.
Lab Time
Start on reading and homework for next week, and meet with Dan about mid-term presentation topics.
WDIM387 Week 2JavaScript functions
By danmuzyka
WDIM387 Week 2JavaScript functions
- 1,457