Instructor: Dan Muzyka
danmuzyka.ai@gmail.com
if (porridge === 'too hot') {
spitOut();
}
else if (porridge === 'too cold') {
pourDownDrain();
}
// Else porridge is 'just right'
else {
devour();
}
switch (porridge) {
case 'too hot':
spitOut();
break;
case 'too cold':
pourDownDrain();
break;
// Otherwise, assume 'just right'
default:
devour();
break;
}
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;
}
var bowlsOfPorridge = [hotBowl, coldBowl, justRightBowl];
for (var i = 0; i < bowlsOfPorridge.length; i++) {
taste(bowlsOfPorridge[i]);
}
var bowlsOfPorridge = [hotBowl, coldBowl, justRightBowl];
for (var i = 0, numBowls = bowlsOfPorridge.length; i < numBowls; i++) {
taste(bowlsOfPorridge[i]);
}
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?
var bowlsOfPorridge = [hotBowl, coldBowl, justRightBowl],
i = bowlsOfPorridge.length - 1;
do {
taste(bowlsOfPorridge[i]);
i--;
} while (i >= 0);
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);
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);
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--;
}
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++;
}
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++;
}
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++;
}
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
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();
// 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();
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 are first-class objects.
Functions can be assigned to variables.
var isPorridgeTasty = function(bowl) {
return (bowl === 'just right bowl');
};
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');
};
// 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
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 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);
What are some examples of callbacks you have seen in your experience with JavaScript?
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
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());
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.
Start on reading and homework for next week, and meet with Dan about mid-term presentation topics.