Almost all languages have the concept of operators1 and conditionals;2 JavaScript and CoffeeScript are no different. Operators and conditionals work hand in hand to form an important part of all programming languages. Operators let you do things such as add or subtract two numbers, compare two objects, shift bytes in an object, and so on. Conditionals, on the other hand, let us control the flow of our application based on certain predefined conditions. For example if a user is not logged in then send them to the login screen, else show them the secret page. That is a conditional statement.
In this chapter we take a look at both operators and conditionals and how they are defined in CoffeeScript.
For the most part, JavaScript and CoffeeScript play nicely in terms of the operators behaving the same. However, in a few places CoffeeScript steps in to help make sure you don’t step on some land mines that JavaScript has lurking about its innards. To make sure we understand fully what all the operators do, let’s take a quick tour of the JavaScript operators, and I’ll point out when they are different from their CoffeeScript counterparts. Before we continue, I want to say that I am assuming you know what all the JavaScript operators do. If you don’t, now is a good time to brush up on them. If you need a reference, I recommend http://en.wikibooks.org/wiki/JavaScript/Operators. It offers a quick, but well written, overview of the operators available in JavaScript.
Here is a list of each of the arithmetic operators in JavaScript:
• +
Addition
• -
Subtraction
• /
Division (returns a floating-point value)
• %
Modulus (returns the integer remainder)
• +
Unary conversion of string to number
• -
Unary negation (reverses the sign)
• ++
Increment (can be prefix or postfix)
• --
Decrement (can be prefix or postfix)
Now let’s take a look at how those operators translate in the CoffeeScript world:
console.log "+ Addition: #{1 + 1}"
console.log "- Subtraction: #{10 - 1}"
console.log "* Multiplication: #{5 * 5}"
console.log "/ Division: #{100 / 10}"
console.log "% Modulus: #{10 % 3}"
console.log "+ Unary conversion of string to number: #{+'100'}"
console.log "- Unary negation: #{-50}"
i = 1
x = ++i
console.log "++ Increment: #{x}"
i = 1
x = --i
console.log "-- Decrement: #{x}"
(function() {
var i, x;
console.log("+ Addition: " + (1 + 1));
console.log("- Subtraction: " + (10 - 1));
console.log("* Multiplication: " + (5 * 5));
console.log("/ Division: " + (100 / 10));
console.log("% Modulus: " + (10 % 3));
console.log("+ Unary conversion of string to number: " + (+'100'));
console.log("- Unary negation: " + (-50));
i = 1;
x = ++i;
console.log("++ Increment: " + x);
i = 1;
x = --i;
console.log("-- Decrement: " + x);
}).call(this);
+ Addition: 2
- Subtraction: 9
* Multiplication: 25
/ Division: 10
% Modulus: 1
+ Unary conversion of string to number: 100
- Unary negation: -50
++ Increment: 2
-- Decrement: 0
As we can see from the example, all our CoffeeScript arithmetic operators map directly to JavaScript, so we won’t be losing any sleep at night trying to remember them.
Now we’ll move on to the assignment operators in JavaScript, which are presented in the following list:
• +=
Add and assign
• -=
Subtract and assign
• *=
Multiply and assign
• /=
Divide and assign
• %=
Modulus and assign
• ?=
Exists or assign
• ||=
Or or assign
• &&=
Assign if both are true
How do they map to CoffeeScript?
console.log "= Assign:"
x = 10
console.log x
console.log "+= Add and assign:"
x += 25
console.log x
console.log "-= Subtract and assign:"
x -= 25
console.log x
console.log "*= Multiply and assign:"
x *= 10
console.log x
console.log "/= Divide and assign:"
x /= 10
console.log x
console.log "%= Modulus and assign:"
x %= 3
console.log x
console.log "?= Exists or assign:"
y ?= 3
console.log y
y ?= 100
console.log y
console.log "||= Or or assign:"
z = null
z ||= 10
console.log z
z ||= 100
console.log z
console.log "&&= Assign if both are true:"
a = 1
b = 2
console.log a &&= b
console.log a
(function() {
var a, b, x, z;
console.log("= Assign:");
x = 10;
console.log(x);
console.log("+= Add and assign:");
x += 25;
console.log(x);
console.log("-= Subtract and assign:");
x -= 25;
console.log(x);
console.log("*= Multiply and assign:");
x *= 10;
console.log(x);
console.log("/= Divide and assign:");
x /= 10;
console.log(x);
console.log("%= Modulus and assign:");
x %= 3;
console.log(x);
console.log("?= Exists or assign:");
if (typeof y === "undefined" || y === null) y = 3;
console.log(y);
if (typeof y === "undefined" || y === null) y = 100;
console.log(y);
console.log("||= Or or assign:");
z = null;
z || (z = 10);
console.log(z);
z || (z = 100);
console.log(z);
console.log("&&= Assign if both are true:");
a = 1;
b = 2;
console.log(a && (a = b));
console.log(a);
}).call(this);
= Assign:
10
+= Add and assign:
35
-= Subtract and assign:
10
*= Multiply and assign:
100
/= Divide and assign:
10
%= Modulus and assign:
1
?= Exists or assign:
3
3
||= Or or assign:
10
10
&&= Assign if both are true:
2
2
Again, all the operators map directly. Isn’t life wonderful?
Now let’s take a look at the comparison operators and see how they map between CoffeeScript and JavaScript.
• ==
Equal
• !=
Not equal
• >
Greater than
• >=
Greater than or equal to
• <
Less than
• <=
Less than or equal to
• ===
Identical (equal and of the same type)
• !==
Not identical
Okay, let’s take a peek and see how these operators behave in CoffeeScript:
console.log "== Equal: #{1 == 1}"
console.log "!= Not equal: #{1 != 2}"
console.log "> Greater than: #{2 > 1}"
console.log ">= Greater than or equal to: #{1 >= 1}"
console.log "< Less than: #{1 < 2}"
console.log "<= Less than or equal to: #{1 < 2}"
console.log "=== Identical: #{'a' === 'a'}"
console.log "!== Not identical: #{1 !== 2}"
Error: In content/control_structures/comparison.coffee, Parse error on line 13: Unexpected '='
at Object.parseError (/usr/local/lib/node_modules/coffee-script/lib/coffee-script/parser.js:470:11)
at Object.parse (/usr/local/lib/node_modules/coffee-script/lib/coffee-script/parser.js:546:22)
at /usr/local/lib/node_modules/coffee-script/lib/coffee-script/coffee-script.js:40:22
at Object.run /usr/local/lib/node_modules/coffee-script/lib/coffee-script/coffee-script.js:68:34)
at /usr/local/lib/node_modules/coffee-script/lib/coffee-script/command.js:135:29
at /usr/local/lib/node_modules/coffee-script/lib/coffee-script/command.js:110:18
at [object Object].<anonymous> (fs.js:114:5)
at [object Object].emit (events.js:64:17)
at afterRead (fs.js:1081:12)
at Object.wrapper [as oncomplete] (fs.js:252:17)
Well, that doesn’t look right, does it? Let’s look at what happened there and why our example blew up. CoffeeScript does not allow the use of the ===
or !==
operators. Hopefully, by the time this book goes to print a better error message will be presented that is both clearer and more informative. I can hear everyone crying out in horror because those are the comparison operators we should be using the most, but don’t worry, CoffeeScript does have our backs here. Let me explain.
Let’s rebuild our example code; this time we’ll drop our ===
and !==
examples:
console.log "== Equal: #{1 == 1}"
console.log "!= Not equal: #{1 != 2}"
console.log "> Greater than: #{2 > 1}"
console.log ">= Greater than or equal to: #{1 >= 1}"
console.log "< Less than: #{1 < 2}"
console.log "<= Less than or equal to: #{1 < 2}"
(function() {
console.log("== Equal: " + (1 === 1));
console.log("!= Not equal: " + (1 !== 2));
console.log("> Greater than: " + (2 > 1));
console.log(">= Greater than or equal to: " + (1 >= 1));
console.log("< Less than: " + (1 < 2));
console.log("<= Less than or equal to: " + (1 < 2));
}).call(this);
== Equal: true
!= Not equal: true
> Greater than: true
>= Greater than or equal to: true
< Less than: true
<= Less than or equal to: true
Great! Our examples didn’t blow up this time, but you should’ve noticed something very interesting. Did you see how our ==
and !=
examples converted when compiled in JavaScript? CoffeeScript compiled those examples into ===
and !==
respectively. Why did CoffeeScript do that? Let’s look at what happens in JavaScript when you use ==
and !=
:
x = 1;
y = '1';
console.log(x == y); // true
In the JavaScript example, 1
is equal to "1"
despite the fact that they are different objects. The reason is that when using the ==
comparison operator in JavaScript it will automatically coerce the two objects to the same type of object and then do the comparison on it. The same holds true for the !=
operator. This is the source of a great many JavaScript bugs. To get a true comparison of two objects you must use the ===
operator.
If we look at the same example again, only this time using the ===
operator, you see that we get false
for our comparison instead of true
:
x = 1;
y = '1';
console.log(x === y); // false
To make sure you don’t run into these sorts of bugs, CoffeeScript automatically converts any ==
and !=
operators into ===
and !==
for you. Isn’t that nice? CoffeeScript is helping you keep your bugs to a minimum. You should send it a thank you card. There is another way to use the ===
and !==
operators, which we’ll look at in a minute when we discuss aliases.
Finally, there are a few operators that work on strings.
• +
Concatenation
• +=
Concatenate and assign
Here they are in CoffeeScript:
console.log "+ Concatenation: #{'a' + 'b'}"
x = 'Hello'
x += " World"
console.log "+= Concatenate and assign: #{x}"
(function() {
var x;
console.log("+ Concatenation: " + ('a' + 'b'));
x = 'Hello';
x += " World";
console.log("+= Concatenate and assign: " + x);
}).call(this);
+ Concatenation: ab
+= Concatenate and assign: Hello World
Fortunately, these operators work just like they do in JavaScript.
When I first discovered CoffeeScript, I immediately fell in love with the existential operator. This operator lets you check, well, the existence of a variable or function, using a simple ?
.
Let’s take a quick look:
console.log x?
(function() {
console.log(typeof x !== "undefined" && x !== null);
}).call(this);
false
As you can see in our example, CoffeeScript generates JavaScript that checks to see if the variable x
is defined; if it is, then it checks to see if it is not null. This can make writing conditionals very powerful.
if html?
console.log html
(function() {
if (typeof html !== "undefined" && html !== null) console.log(html);
}).call(this);
The fun doesn’t stop there with the existential operator. Using the existential operator, we can check the existence of something, and if it exists, call a function on it. My favorite example of this is with the console
object. For those of you unfamiliar with the console
object, it exists in most browsers as a way to write messages to the built-in JavaScript error console. Typically, this is used by developers as a way of logging messages at certain points in the code for either debugging or informational purposes. I’ve been using it in almost all the book examples as a way to demonstrate the output of our examples.
The problem with the console
object is that it isn’t always there (Internet Explorer, I’m looking at you!). If you attempt to call a function or call a property on a variable that doesn’t exist, the browser will raise an exception and your program will not execute properly. The existential operator can help us get around the problem of calling functions on objects that are not defined, such as the console
object in certain browsers.
First, let’s look at an example where we don’t use the existential operator:
console.log "Hello, World"
console.log someObject.someFunction()
console.log "Goodbye, World"
(function() {
console.log("Hello, World");
console.log(someObject.someFunction());
console.log("Goodbye, World");
}).call(this);
Hello, World
ReferenceError: someObject is not defined
at Object.<anonymous> (.../control_structures/existential2.coffee:5:15)
at Object.<anonymous> (.../control_structures/existential2.coffee:9:4)
at Module._compile (module.js:432:26)
at Object.run (/usr/local/lib/node_modules/coffee-script/lib/coffee-script/coffee-script.js:68:25)
at /usr/local/lib/node_modules/coffee-script/lib/coffee-script/command.js:135:29
at /usr/local/lib/node_modules/coffee-script/lib/coffee-script/command.js:110:18
at [object Object].<anonymous> (fs.js:114:5)
at [object Object].emit (events.js:64:17)
at afterRead (fs.js:1081:12)
at Object.wrapper [as oncomplete] (fs.js:252:17)
Well, that’s a nasty little error, isn’t it? Our example is blowing up because it cannot find an object named someObject
and we are attempting to call a function. Now, if we add the existential operator after someObject
, let’s see what happens.
console.log "Hello, World"
console.log someObject?.someFunction()
console.log "Goodbye, World"
(function() {
console.log("Hello, World");
console.log(typeof someObject !== "undefined" && someObject !== null ? someObject.someFunction() : void 0);
console.log("Goodbye, World");
}).call(this);
Hello, World
undefined
Goodbye, World
That is definitely better. Although we got an undefined
message when we tried to access our someObject
variable, the program did fully execute. If this were a real-world example, we might want to log a message or possibly raise some sort of alert, but for now I think we’ve done our part to make our code a little safer.
In an effort to make your code a little more user friendly, CoffeeScript has added a few aliases for some of the more common operators. Some of these aliases make wonderful additions to the language, but others are a little confusing. Table 3.1 shows the CoffeeScript aliases and their JavaScript counterparts.
Let’s take a look at all but the last two aliases. The last two aliases will be covered in Chapter 5, “Collections and Iterations.”
is
and isnt
AliasesHere is an example of the is
, isnt
operator aliases in action:
name = "mark"
console.log name is "mark"
console.log name isnt "bob"
(function() {
var name;
name = "mark";
console.log(name === "mark");
console.log(name !== "bob");
}).call(this);
true
true
As you can see, in our code the is
alias mapped to the ===
and the isnt
operator mapped to the !==
. As you recall from our earlier discussions in this chapter, the ===
and !==
operators are the comparison operators CoffeeScript not only wants you to use, but insists you use. CoffeeScript also would prefer you to use the is
and isnt
aliases. They are considered “the CoffeeScript way.” Removing the ==
and !=
as legal operators from CoffeeScript and forcing the use of the is
and isnt
operators only has been discussed. As of the time of this writing this has not happened, but it is something you should be aware of. This particular caveat holds true of all the aliases and their appropriate matching operator.
not
AliasThe not
alias and I have a love/hate relationship. I love the way it makes my code look, but I hate the way it doesn’t always behave the way I want it to. The idea of the not
alias is the same as the !
operator in JavaScript; it will “flip” the Boolean state of a variable. That means it will make a true
become false
and vice versa.
Let’s take a look at how the not
alias behaves:
userExists = false
if not userExists
console.log "the user doesn't exist!"
(function() {
var userExists;
userExists = false;
if (!userExists) console.log("the user doesn't exist!");
}).call(this);
the user doesn't exist!
As you can see, we have to make sure to place a space between the not
alias and the variable we are trying to “flip” Boolean states on.
So how does this get confusing? In CoffeeScript it is possible to write this code:
name = "mark"
console.log name isnt "bob"
console.log name is not "bob"
(function() {
var name;
name = "mark";
console.log(name !== "bob");
console.log(name === !"bob");
}).call(this);
true
false
Although grammatically those couple of lines look correct, they are actually very different lines of code. The line using the isnt
alias is checking that the two objects are not equal. The line using the is not
alias is checking the equality of the first variable to the “flipped” Boolean value of the second. This is an easy mistake to make, especially when you are first starting with CoffeeScript.
and
and or
AliasesI love these aliases. The and
and or
aliases not only read well in your code, but they do just what you would expect them to do! Here’s an example:
if true and true
console.log "true and true really is true"
if false or true
console.log "something was true"
(function() {
if (true && true) console.log("true and true really is true");
if (false || true) console.log("something was true");
}).call(this);
true and true really is true
something was true
Like I said, they do just what you would expect them to do.
CoffeeScript supports not just true
and false
for Booleans, but also took a page from the book of YAML3 and added a few other aliases to make your code nicer to read.
Let’s have a look:
myAnswer = true
console.log myAnswer is yes
console.log myAnswer is true
light = true
console.log light is on
console.log light is true
myAnswer = false
console.log myAnswer is no
console.log myAnswer is false
light = false
console.log light is off
console.log light is false
(function() {
var light, myAnswer;
myAnswer = true;
console.log(myAnswer === true);
console.log(myAnswer === true);
light = true;
console.log(light === true);
console.log(light === true);
myAnswer = false;
console.log(myAnswer === false);
console.log(myAnswer === false);
light = false;
console.log(light === false);
console.log(light === false);
}).call(this);
true
true
true
true
true
true
true
true
As you can see the yes
, no
, on
, and off
aliases can make your code fun and easy to read.
@
AliasThe last alias we look at before we move on is the @
alias. We will revisit this alias from time to time throughout the book as we talk about different areas of CoffeeScript. For now let’s talk about its most basic, and common, use: as an alias for the JavaScript keyword this
.
Here is a very simple example of the @
alias at work:
object = {
name: 'mark'
sayHi: ->
console.log "Hello: #{@name}"
}
object.sayHi()
console.log @name
(function() {
var object;
object = {
name: 'mark',
sayHi: function() {
return console.log("Hello: " + this.name);
}
};
object.sayHi();
console.log(this.name);
}).call(this);
Hello: mark
undefined
If you don’t understand how this
scoping in JavaScript works, or even what this
is, I urge you to put this book down now and pick up a proper JavaScript book and read that first.
As you can see, if you compare our CoffeeScript example and its compiled JavaScript output, all references to @
were replaced with this.
when compiled. I find that my code is much easier to read when using the @
symbol. I can easily distinguish between “local” variables, sometimes referred to as instance variables, within a function and variables and functions that are defined outside of the current function I’m working in.
In my travels as a developer, I have yet to meet a programming language that didn’t have the concept of conditional statements. I’m sure somebody out there has written one, but I doubt that it is heavily used outside of that person’s parent’s basement.
Conditionals allow our programs to become intelligent. They let us program applications that can react to different situations. Is there a logged in user? If not, ask her to log in; otherwise, show her the secret account page. Has the current user paid his bill? If he has, give him access to his account; if not, tell him to pay. These are examples of conditional statements. The program takes a different path through its execution based on the answers to these questions.
CoffeeScript, like almost every other programming language, offers conditionals. These conditional statements will typically be used with the operators and aliases we’ve already seen in this chapter to help the program make more intelligent decisions.
if
StatementAlready in this book, you have seen examples of the if
statement at work. The structure is pretty simple.
if true
console.log "the statement was true"
(function() {
if (true) console.log("the statement was true");
}).call(this);
the statement was true
Our example, while incredibly contrived, illustrates the structure of an if
statement. We follow the keyword if
with whatever our conditional statement is. If that statement returns true
we execute the block of code following it. If the conditional statement returns false
we skip execution of the code block.
Here is a slightly less-contrived example:
today = "Sunday"
if today is "Sunday"
console.log "Today is Sunday"
(function() {
var today;
today = "Sunday";
if (today === "Sunday") console.log("Today is Sunday");
}).call(this);
Today is Sunday
if/else
StatementThere are times when we want to execute some code if the conditional statement is true, and there are times when we want to execute some other code if the statement is false. In these cases we can use the if
statement we know and the else
keyword to define a block of code to run, should the conditional statement be false.
For example:
today = "Monday"
if today is "Sunday"
console.log "Today is Sunday"
else
console.log "Today is not Sunday"
(function() {
var today;
today = "Monday";
if (today === "Sunday") {
console.log("Today is Sunday");
} else {
console.log("Today is not Sunday");
}
}).call(this);
Today is not Sunday
As you can see, in our example our conditional was false, so the block of code defined after the else
keyword was executed.
CoffeeScript does allow you to write this in a single line of code, which would look something like this:
today = "Monday"
console.log if today is "Sunday" then "Today is Sunday" else "Today is not Sunday"
(function() {
var today;
today = "Monday";
console.log(today === "Sunday" ? "Today is Sunday" : "Today is not Sunday");
}).call(this);
Today is not Sunday
Personally, I think that the single line if else then
statement is a bit wordy and hard to read, so I would very rarely, if ever, use it.
In JavaScript you can use what is called the ternary operator4 to write that same example in one line of code, which is what CoffeeScript compiles it down to. However, CoffeeScript does not support the ternary operator, so any attempt to use it would result in some rather strange compiled JavaScript. Take a look for yourself:
today = "Monday"
console.log today is "Sunday" ? "Today is Sunday" : "Today is not Sunday"
(function() {
var today, _ref;
today = "Monday";
console.log((_ref = today === "Sunday") != null ? _ref : {
"Today is Sunday": "Today is not Sunday"
});
}).call(this);
false
I’m not going to explain what happened there. Make a note to yourself to revisit this example when you have finished this book to see if you can solve the riddle of why CoffeeScript generated that JavaScript.
if/else if
StatementLet’s pretend for a moment that we are writing a very basic todo application. When we look at the application we want it do one of three things. If today is Saturday, we want it to show us a list of todos for the day. If it’s Sunday, we want it to tell us to relax and enjoy the day. Finally if it’s neither Saturday nor Sunday, we want it tell us to get to work. How would we write that using the knowledge we have so far? It would look something like this:
today = "Monday"
if today is "Saturday"
console.log "Here are your todos for the day..."
if today is "Sunday"
console.log "Go watch football and relax!"
if today isnt "Saturday" and today isnt "Sunday"
console.log "Get to work you lazy bum!"
(function() {
var today;
today = "Monday";
if (today === "Saturday") console.log("Here are your todos for the day...");
if (today === "Sunday") console.log("Go watch football and relax!");
if (today !== "Saturday" && today !== "Sunday") {
console.log("Get to work you lazy bum!");
}
}).call(this);
Get to work you lazy bum!
Although that code does work, it isn’t the most efficient code. For a start we are checking each if
statement, even if the first one was true
, and we still check the other if
statements in case they are also true, which we know will never be the case. Also, our last if
statement is a bit repetitive because we are asking similar questions already. Finally, it is also error prone. If want to change from using full day names, like Sunday, to shortened ones, like Sun, we have to make sure we update every reference to Sunday we find.
Using the else if
statement, we can easily clean up this example. Here’s how:
today = "Monday"
if today is "Saturday"
console.log "Here are your todos for the day..."
else if today is "Sunday"
console.log "Go watch football and relax!"
else
console.log "Get to work you lazy bum!"
(function() {
var today;
today = "Monday";
if (today === "Saturday") {
console.log("Here are your todos for the day...");
} else if (today === "Sunday") {
console.log("Go watch football and relax!");
} else {
console.log("Get to work you lazy bum!");
}
}).call(this);
Get to work you lazy bum!
Now doesn’t that look a lot better? It is also a lot more efficient when executed. If today were Saturday, it would execute the first code block and then skip the rest of the else if
and else
statements, because they are unnecessary.
Later in this chapter we will rewrite this example using the switch
statement, which will clean it up even further.
unless
StatementThe Ruby programming language has the concept of the unless
statement, and the folks behind CoffeeScript thought it was such a great idea they stole it.
What does the unless
statement do? In short, it enables you to put the else
before the if
. Now, I know you’re scratching your head. It is confusing at first, but it really is straightforward.
When using the unless
we are checking to see if our conditional statement is false. If the statement is false, we execute the code block defined below it. Here’s an example:
today = "Monday"
unless today is "Sunday"
console.log "No football today!"
(function() {
var today;
today = "Monday";
if (today !== "Sunday") console.log("No football today!");
}).call(this);
No football today!
The same example could be written in any of the following ways:
today = "Monday"
unless today is "Sunday"
console.log "No football today!"
if not (today is "Sunday")
console.log "No football today!"
if today isnt "Sunday"
console.log "No football today!"
(function() {
var today;
today = "Monday";
if (today !== "Sunday") console.log("No football today!");
if (!(today === "Sunday")) console.log("No football today!");
if (today !== "Sunday") console.log("No football today!");
}).call(this);
No football today!
No football today!
No football today!
Of the three examples, I prefer the last example using the isnt
alias. I find it to be a bit cleaner and easier to read. The choice, however, is up to you. They are all valid ways of writing the same code.
In addition to the unless
keyword, the CoffeeScript team copped the idea of inline conditionals from Ruby. An inline conditional statement allows you to place both the conditional statement and the code block to execute on the same line.
This is easily demonstrated with an example:
today = "Sunday"
console.log "Today is Sunday" if today is "Sunday"
(function() {
var today;
today = "Sunday";
if (today === "Sunday") console.log("Today is Sunday");
}).call(this);
Today is Sunday
When used with the existential operator, which we covered earlier in this chapter, the inline conditional can help to keep code clean.
Earlier when we talked about else if
statements, I mentioned how we could clean up that code using a switch
statement.5 A switch
statement lets us build a table of conditionals, which we can then match an object against. Should one of the conditionals match, appropriate code will be executed. We can also give our table an else
clause to match, should none of the other conditionals match.
Let’s take a look at our earlier else if
example and rewrite it to use the switch
statement in CoffeeScript.
today = "Monday"
switch today
when "Saturday"
console.log "Here are your todos for the day..."
when "Sunday"
console.log "Go watch football and relax!"
else
console.log "Get to work you lazy bum!"
(function() {
var today;
today = "Monday";
switch (today) {
case "Saturday":
console.log("Here are your todos for the day...");
break;
case "Sunday":
console.log("Go watch football and relax!");
break;
default:
console.log("Get to work you lazy bum!");
}
}).call(this);
Get to work you lazy bum!
As you can see, our today
variable is checked against the defined case
statements. Because neither of the case
statements matched the today
variable we passed in, the program fell through to the else
statement we defined at the end of the switch
statement. It’s worth pointing out that we don’t need to define an else
block at the end. If we didn’t define the else
in our example, nothing would have been printed out.
The more observant of you will have noticed the break
keyword in the compiled JavaScript output at the end of each of the case
statements. In JavaScript it is possible to let the switch
statement keep falling through and keep matching more case
statements. This is almost never wanted, and is often the source of many bugs. The most common bug is that it matches a case, executes the appropriate code, and ends up also executing the default
code block at the bottom. The break
keyword will tell the switch
to stop executing and to stop trying to match other cases. This is another example of CoffeeScript trying to cover your back and help you write code with fewer bugs.
The switch
statement also enables us to pass a comma-separated list of values to match against the case
keyword. This makes it possible for us to execute the same code block for multiple matches. Suppose we wanted a program that would check to see if today was a weekend day. If it was indeed a weekend day, it would tell us to relax; otherwise, it would tell us to work. We could do that like this:
today = "Sunday"
switch today
when "Saturday", "Sunday"
console.log "Enjoy your #{today}!"
else
console.log "Off to work you go. :("
(function() {
var today;
today = "Sunday";
switch (today) {
case "Saturday":
case "Sunday":
console.log("Enjoy your " + today + "!");
break;
default:
console.log("Off to work you go. :(");
}
}).call(this);
Enjoy your Sunday!
With that, our exploration of the wonderful switch
statement comes to a close. There is a lot of debate among developers as to when, where, or if you should ever use switch
statements. They are not something I use on a day-to-day basis, but they definitely have their place. I’ll let you decide when they are of use to you and your application.
In this chapter we’ve covered a lot of ground. We’ve discussed the various operators in CoffeeScript and how, if at all, they map to JavaScript. We’ve seen a few of the places where CoffeeScript tries to help us write better JavaScript code. Aliases showed us how to write “prettier” code that reads more like English than “computer.” You’ve seen how to build conditional statements to help make your programs more intelligent and to help execute the correct bit of code depending on certain conditions. Finally, we explored how the switch
statement can help you clean up complex code.
In the original outline for this book, this chapter was originally part of Chapter 2, “The Basics,” but I felt there was so much information here that it deserved its own chapter. This chapter could have been called “The Basics—Part 2.” I’m telling you this because, armed with the knowledge contained within this chapter and Chapter 2, we have covered the basic building blocks of CoffeeScript. We can now start looking at the really fun stuff.
1. http://en.wikipedia.org/wiki/Operator_(programming)
2. http://en.wikipedia.org/wiki/Conditional_(programming)
3. http://www.yaml.org/spec/1.2/spec.html
18.227.190.211