Types, Equality, Conversion and All That Jazz: Serious types - Head First JavaScript Programming (2014)

Head First JavaScript Programming (2014)

Chapter 7. Types, Equality, Conversion and All That Jazz: Serious types

image with no caption

It’s time to get serious about our types. One of the great things about JavaScript is you can get a long way without knowing a lot of details of the language. But to truly master the language, get that promotion and get on to the things you really want to do in life, you have to rock at types. Remember what we said way back about JavaScript? That it didn’t have the luxury of a silver-spoon, academic, peer-reviewed language definition? Well that’s true, but the academic life didn’t stop Steve Jobs and Bill Gates, and it didn’t stop JavaScript either. It does mean that JavaScript doesn’t have the... well, the most thought-out type system, and we’ll find a few idiosyncrasies along the way. But, don’t worry, in this chapter we’re going to nail all that down, and soon you’ll be able to avoid all those embarrassing moments with types.

The truth is out there...

Now that you’ve had a lot of experience working with JavaScript types—there’s your primitives with numbers, strings, and booleans, and there’s all the objects, some supplied by JavaScript (like the Math object), some supplied by the browser (like the document object), and some you’ve written yourself—aren’t you just basking in the glow of JavaScript’s simple, powerful and consistent type system?

image with no caption

After all what else would you expect from the official language of Webville? In fact, if you were a mere scripter, you might think about sitting back, sipping on that Webville Martini, and taking a much needed break...

But you’re not a mere scripter, and something is amiss. You have that sinking feeling that behind Webville’s picket fences something bizarre is at work. You’ve heard the reports of sightings of strings that are acting like objects, you’ve read in the blogs about a (probably radioactive) null type, you’ve heard the rumors that the JavaScript interpreter as of late has been doing some weird type conversion. What does it all mean? We don’t know, but the truth is out there and we’re going to uncover it in this chapter, and when we do, we might just turn what you think of true and false upside down.

image with no caption

WHO AM I?

image with no caption

A bunch of JavaScript values and party crashers, in full costume, are playing a party game, “Who am I?” They give you a clue, and you try to guess who they are, based on what they say. Assume they always tell the truth about themselves. Draw an arrow from each sentence to the name of one attendee. We’ve already guessed one of them for you. Check your answers at the end of the chapter before you go on.

If you find this exercise difficult, it’s okay to cheat and look at the answers.

image with no caption

Watch out, you might bump into undefined when you aren’t expecting it...

As you can see, whenever things get shaky—you need a variable that’s not been initialized yet, you want a property that doesn’t exist (or has been deleted), you go after an array item that isn’t there—you’re going to encounter undefined.

image with no caption

But what the heck is it? It’s not really that complicated. Think of undefined as the value assigned to things that don’t yet have a value (in other words they haven’t been initialized).

So what good is it? Well, undefined gives you a way to test to see if a variable (or property, or array item) has been given a value. Let’s look at a couple of examples, starting with an unassigned variable:

image with no caption

Or, how about an object property:

image with no caption

THERE ARE NO DUMB QUESTIONS

Q:

Q: When do I need to check if a variable (or property or array item) is undefined?

A:

A: Your code design will dictate this. If you’ve written code so that a property or variable may not have a value when a certain block of code is executed, then checking for undefined gives you a way to handle that situation rather than computing with undefined values.

Q:

Q: If undefined is a value, does it have a type?

A:

A: Yes, it does. The type of undefined is undefined. Why? Well our logic (work with us here) is this: it isn’t an object, or a number or a string or a boolean, or really anything that is defined. So why not make the type undefined, too? This is one of those weird twilight zones of JavaScript you just have to accept.

IN THE LABORATORY

image with no caption

In the laboratory we like to take things apart, look under the hood, poke and prod, hook up our diagnostic tools and check out what is really going on. Today, we’re investigating JavaScript’s type system and we’ve found a little diagnostic tool called typeof to examine variables. Put your lab coat and safety goggles on, and come on in and join us.

The typeof operator is built into JavaScript. You can use it to probe the type of its operand (the thing you use it to operate on). Here’s an example:

image with no caption

image with no caption

Ah yes, this causes a lot of confusion. There are many languages that have the concept of a value that means “no object.” And, it’s not a bad idea—take the document.getElementById method. It’s supposed to return an object right? So, what happens if it can’t? Then we want to return something that says “I would have been an object if there was one, but we don’t have one.” And that’s what null is.

You can also set a variable to null directly:

var killerObjectSomeday = null;

What does it mean to assign the value null to a variable? How about “We intend to assign an object to this variable at some point, but we haven’t yet.”

Now, if you’re scratching your head and saying “Hmm, why didn’t they just use undefined for that?” then you’re in good company. The answer comes from the very beginnings of JavaScript. The idea was to have one value for variables that haven’t been initialized to anything yet, and another that means the lack of an object. It isn’t pretty, and it’s a little redundant, but it is what it is at this point. Just remember the intent of each (undefined and null), and know that it is most common to use null in places where an object should be but one can’t be created or found, and it is most common to find undefined when you have a variable that hasn’t been initialized, or an object with a missing property, or an array with a missing value.

BACK IN THE LABORATORY

Oops, we forgot null in our test data. Here’s the missing test case:

var test10 = null;

console.log(typeof test10);

image with no caption

How to use null

There are many functions and methods out there in the world that return objects, and you’ll often want to make sure what you’re getting back is a full-fledged object, and not null, just in case the function wasn’t able to find one or make one to return to you. You’ve already seen examples from the DOM where a test is needed:

image with no caption

Keep in mind that getting null doesn’t necessarily mean something is wrong. It may just mean something doesn’t exist yet and needs to be created, or something doesn’t exist and you can skip it. Let’s say users have the ability to open or close a weather widget on your site. If a user has it open there’s a <div> with the id of “weatherDiv”, and if not, there isn’t. All of a sudden null becomes quite useful:

image with no caption

Remember, null is intended to represent an object that isn’t there.

BLAINE, MISSOURI

It is always 67 degrees with a 40% chance of rain.

image with no caption

We can use null to check to see if an object exists yet or not.

image with no caption

Dealing with NaN

Now you might think that dealing with NaN is a rare event, but if you’re working with any kind of code that uses numbers, you’d be surprised how often it shows up. The most common thing you’ll need to do is test for NaN, and given everything you’ve learned about JavaScript, how to do this might seem obvious:

WRONG!

image with no caption

Any sensible person would assume that’s how you test to see if a variable holds a NaN value, but it doesn’t work. Why? Well, NaN isn’t equal to anything, not even itself, so, any kind of test for equality with NaN is off the table. Instead you need to use a special function: isNaN. Like this:

RIGHT!

image with no caption

It gets even weirder

So, let’s think through this a bit more. If NaN stands for “Not a Number”, what is it? Wouldn’t it be easier if it were named for what it is rather than what it isn’t? What do you think it is? We can check its type for a hint:

var test11 = 0 / 0;

console.log(typeof test11);

image with no caption

What on earth? NaN is of type number? How can something that’s not a number have the type number? Okay, deep breath. Think of NaN as just a poorly named value. Someone should have called it something more like “Number that can’t be represented” (okay, we agree the acronym isn’t quite as nice) instead of “Not a Number”. If you think about it like that, then you can think of NaN as being a value that is a number but can’t be represented (at least, not by a computer).

Go ahead and add this one to your JavaScript twilight zone list.

THERE ARE NO DUMB QUESTIONS

Q:

Q: If I pass isNaN a string, which isn’t a number, will it return true?

A:

A: It sure will, just as you’d expect. You can expect a variable holding the value NaN, or any other value that isn’t an actual number to result in isNaN returning true (and false otherwise). There are a few caveats to this that you’ll see when we talk about type conversion.

Q:

Q: But why isn’t NaN equal to itself?

A:

A: If you’re deeply interested in this topic you’ll want to seek out the IEEE floating point specification. However, the layman’s insight into this is that just because NaN represents an unrepresentable numeric value, does not mean that those unrepresentable numbers are equal. For instance, take the sqrt(-1) and sqrt(-2). They are definitely not the same, but they both produce NaN.

Q:

Q: When we divide 0/0 we get NaN, but I tried dividing 10/0 and got Infinity. Is that different from NaN?

A:

A: Good find. The Infinity (or -Infinity) value in JavaScript represents all numbers (to get a little technical) that exceed the upper limit on computer floating point numbers, which is 1.7976931348623157E+10308 (or -1.7976931348623157E+10308 for -Infinity). The type of Infinity is number and you can test for it if you suspect one of your values is getting a little large:

if (tamale == Infinity) {

alert("That's a big tamale!");

}

Q:

Q: You did blow my mind with that “NaN is a number” thing. Any other mind blowing details?

A:

A: Funny you should ask. How about Infinity minus Infinity equals.... wait for it........ NaN. We’ll refer you to a good mathematician to understand that one.

Q:

Q: Just to cover every detail, did we say what the type of null is?

A:

A: A quick way to find out is by using the typeof operator on null. If you do that you’ll get back the result “object”. And this makes sense from the perspective that null is used to represent an object that isn’t there. However, this point has been heavily debated, and the most recent spec defines the type of null as null. You’ll find this an area where your browser’s JavaScript implementation may not match the spec, but, in practice, you’ll rarely need to use the type of null in code.

EXERCISE

We’ve been looking at some rather, um, interesting, values so far in this chapter. Now, let’s take a look at some interesting behavior. Try adding the code below to the <script> element in a basic web page and see what you get in the console when you load up the page. You won’t get why yet, but see if you can take a guess about what might be going on.

if (99 == "99") {

console.log("A number equals a string!");

} else {

console.log("No way a number equals a string");

}

image with no caption

We have a confession to make

image with no caption

There is an aspect of JavaScript we’ve deliberately been holding back on. We could have told you up front, but it wouldn’t have made as much sense as it will now.

It’s not so much that we’ve been pulling the wool over your eyes, it’s that there is more to the story than we’ve been telling you. And what is this topic? Here, let’s take a look:

image with no caption

Straightforward enough? Sure, what could be easier? However, one thing we’ve done at least once so far in this book, that you might not have noticed, is something like this:

image with no caption

So what happens when we compare a number to a string? Mass chaos? Computer meltdown? Rioting in the streets?

No, JavaScript is smart enough to determine that 99 and “99” are the same for all practical purposes. But what exactly is going on behind the scenes to make this work? Let’s take a look...

BULLET POINTS

Just a quick reminder about the difference between assignment and equality:

§ var x = 99;

= is the assignment operator. It is used to assign a value to a variable.

§ x == 99

== is a comparison operator. It is used to compare one value with another to see if they’re equal.

Understanding the equality operator (otherwise known as ==)

image with no caption

You’d think that understanding equality would be a simple topic. After all, 1 == 1, “guacamole” == “guacamole” and true == true. But, clearly there is more at work here if “99” == 99. What could be going on inside the equality operator to make that happen?

It turns out the == operator takes the types of its operands (that is, the two things you’re comparing) into account when it does a comparison. You can break this down into two cases:

If the two values have the same type, just compare them

If the two values you are comparing have the same type, like two numbers or two strings, then the comparison works just like you would expect: the two values are compared against each other and the result is true if they are the same value. Easy enough.

If the two values have different types, try to convert them into the same type and then compare them

This is the more interesting case. Say you have two values with different types that you want to compare, like a number and a string. What JavaScript does is convert the string into a number, and then compares the two values. Like this:

NOTE

Note that the conversion is only temporary, so that the comparison can happen.

image with no caption

Okay, that makes some intuitive sense, but what are the rules here? What if I compare a boolean to a number, or null to undefined, or some other combination of values? How do I know what’s going to get converted into what? And, why not convert the number into a string instead, or use some other scheme to test their equality? Well, this is defined by a fairly simple set of rules in the JavaScript specification that determine how the conversion happens when we compare two values with different types. This is one of those things you just need to internalize—once you’ve done that, you’ll be on top of how comparisons work the rest of your JavaScript career.

NOTE

This will also set you above your peers, and help you nail your next interview.

How equality converts its operands (sounds more dangerous than it actually is)

So what we know is that when you compare two values that have different types, JavaScript will convert one type into another in order to compare them. If you’re coming from another language this might seem strange given this is typically something you’d have to code explicitly rather than have it happen automatically. But no worries, in general, it’s a useful thing in JavaScript so long as you understand when and how it happens. And, that’s what we’ve got to figure out now: when it happens and how it happens.

Here we go (in four simple cases):

CASE#1: Comparing a number and a string.

If you’re comparing a string and a number the same thing happens every time: the string is converted into a number, and the two numbers are then compared. This doesn’t always go well, because not all strings can be converted to numbers. Let’s see what happens in that case:

image with no caption

CASE#2: Comparing a boolean with any other type.

In this case, we convert the boolean to a number, and compare. This might seem a little strange, but it’s easier to digest if you just remember that true converts to 1 and false converts to 0. You also need to understand that sometimes this case requires doing more than one type conversion. Let’s look at a few examples:

image with no caption

Here’s another case; this time a boolean is compared to a string. Notice how more steps are needed.

image with no caption

CASE#3: Comparing null and undefined.

Comparing these values evalutates to true. That might seem odd as well, but it’s the rule. For some insight, these values both essentially represent “no value” (that is, a variable with no value, or an object with no value), so they are considered to be equal.

image with no caption

CASE#4: Oh, actually there is no case #4.

That’s it. You can pretty much determine the value of any equality with these rules. That said, there are a few edge cases and caveats. One caveat is that we still need to talk about comparing objects, which we’ll talk about in a bit. The other is around conversions that might catch you off guard. Here’s one example:

image with no caption

image with no caption

How to get strict with equality

image with no caption

While we’re making confessions, here’s another one: there are not one, but two equality operators. You’ve already been introduced to == (equality), and the other operator is === (strict equality).

That’s right, three equals. You can use === in place of == anytime you want, but before you start doing that, let’s make sure you understand how they differ.

With ==, you now know all the complex rules around how the operands are converted (if they’re different types) when they’re compared. With ===, the rules are even more complicated.

Just kidding, actually there is only one rule with ===:

Two values are strictly equal only if they have the same type and the same value.

Read that again. What that means is, if two values have the same type we compare them. If they don’t, forget it, we’re calling it false no matter what—no conversion, no figuring out complex rules, none of that. All you need to remember is that === will find two values equal only if they are the same type and the same value.

SHARPEN YOUR PENCIL

For each comparison below write true or false below the operators == and === to represent the result of the comparison:

image with no caption

THERE ARE NO DUMB QUESTIONS

Q:

Q: What happens if I compare a number, like 99, to a string, like “ninety-nine”, that can’t be converted to a number?

A:

A: JavaScript will try to convert “ninety-nine” to a number, and it will fail, resulting in NaN. So the two values won’t be equal, and the result will be false.

Q:

Q: How does JavaScript convert strings to numbers?

A:

A: It uses an algorithm to parse the individual characters of a string and try to turn each one of them into a number. So if you write “34”, it will look at “3”, and see that can be a 3, and then it will look at “4” and see that can be a 4. You can also convert strings like “1.2” to floating point numbers—JavaScript is smart enough to recognize a string like this can still be a number.

Q:

Q: So, what if I try something like “true” == true?

A:

A: That is comparing a string and a boolean, so according to the rules, JavaScript will first convert true to 1, and then compare “true” and 1. It will then try to convert “true” to a number, and fail, so you’ll get false.

Q:

Q: So if there is both a == and a === operator, does that mean we have <= and <==, and >= and >==?

A:

A: No. There are no <== and >== operators. You can use only <= and >=. These operators only know how to compare strings and numbers (true <= false doesn’t really make sense), so if you try to compare any values other than two strings or two numbers (or a string and a number), JavaScript will attempt to convert the types using the rules we’ve discussed.

Q:

Q: So if I write 99 <= “100” what happens?

A:

A: Use the rules: “100” is converted to a number, and then compared with 99. Because 99 is less than or equal to 100 (it’s less than), the result is true.

Q:

Q: Is there a !==?

A:

A: Yes, and just like === is stricter than ==, !== is stricter than !=. You use the same rules for !== as you do for ===, except that you’re checking for inequality instead of equality.

Q:

Q: Do we use the same rules when we’re comparing say, a boolean and a number with < and >, like 0 < true?

A:

A: Yup! And in that case, true gets converted to 1, so you’ll get true because 0 is less than 1.

Q:

Q: It makes sense for a string to be equal to another string, but how can a string be less than or greater than another string?

A:

A: Good question. What does it mean to say “banana” < “mango”? Well, with strings, you can use alphabetical order to know if one string is less than or greater than another. Because “banana” begins with a “b” and “mango” with an “m”, “banana” is less than “mango” because “b” comes before “m” in the alphabet. And “mango” is less than “melon” because, while the first letters are the same, when we compare the second letters, “a” comes before “e”.

This alphabetical comparison can trip you up, however; for instance, “Mango” < “mango” is true, even though you might think that “M” is greater than “m” because its “M” is capitalized. The ordering of strings has to do with the ordering of the Unicode values that are used to represent each character in the computer (Unicode is a standard for representing characters digitally), and that ordering might not always be what you expect! For all the details, try googling “Unicode”. But most of the time, the basic alphabetical ordering is all you need to know if one string is less than or greater than another.

FIRESIDE CHAT

image with no caption

Tonight’s talk: The equality and strict equality operators let us know who is boss.

==

===

Ah look who it is, Mr. Uptight.

Just keep in mind that several leading JavaScript gurus say that developers should use me, and only me. They think you should be taken out of the language altogether.

I’m up for a count of == versus === across all JavaScript code out in the world. You’re going to come in way behind. It won’t even be close.

You know, you might be right, but folks are slowly starting to get it, and those numbers are changing.

I don’t think so. I provide a valuable service. Who doesn’t want to, say, compare user input in the form of a string to a number every once in a while?

And with it come all the rules you have to keep in mind to even use ==. Keep life and code simple; use === and if you need to convert user input to a number there are methods for that.

When you were in grade school did you have to walk to school in the snow, every day, uphill, in both directions? Do you always have to do things the hard way?

Very funny. There’s nothing wrong with being strict and having clear-cut semantics around your comparisons. Bad, unexpected things can happen if you don’t keep all the rules in mind.

The thing is, not only can I do the same comparisons you do, I add value on top of that by doing some nice conversions of types.

Every time I look at your rules I throw up in my mouth a little. I mean comparing a boolean to anything means I convert the boolean to a number? That doesn’t seem very sensical to me.

You’d rather just throw your hands up, call it false and go home?

No, but one can get a little too lax around your complex rules.

It’s working so far. Look at all the code out there, a lot written by mere... well, scripters.

That’s fine but pages are getting more complex, more sophisticated. It’s time to take on some best practices.

You mean like taking a shower after one of these conversations with you?

No, like sticking to ===. It makes your code clearer and removes the potential for weird edge cases in comparisons.

Hmm. Well, ever considered just buying me out? I’d be happy to go spend my days on the beach, kicking back with a margarita in hand.

I didn’t see that coming, I thought you’d defend your position as THE equality operator until the end. What gives?

Arguing about == versus === gets old. I mean there are more interesting things to do in life.

I don’t even know how to respond.

Look, here’s the thing you have to deal with: people aren’t going to just stop using ==. Sometimes it’s really convenient. And people can use it in an educated way, taking advantage of it when it makes sense. Like the user input example—why the heck not use ==?

Well like I said, you never know when something is going to happen.

My new attitude is if people want to use you, great. I’m still here when they need me, and by the way, I still get a check every month no matter what they do! There’s enough legacy code with == in the world—I’m never going off payroll.

image with no caption

Deep breath. There’s a lot of debate around this topic, and different experts will tell you different things. Here’s our take: traditionally, coders have used mostly == (equality) because, well, there wasn’t a great awareness of the two operators and their differences. Today, we’re more educated and for most purposes === (strict equality) works just fine and is in some ways the safer route because you know what you’re getting. With ==, of course, you also know what you’re getting, but with all the conversions it’s hard sometimes to think through all the possibilities.

Now, there are times when == provides some nice convenience (like when you’re comparing numbers to strings) and of course you should feel free to use == in those cases, especially now that, unlike many JavaScript coders, you know exactly what == does. Now that we’ve talked about ===, you’ll see us mostly shift gears in this book and predominantly use ===, but we won’t get dogmatic about it if there’s a case where == makes our life easier and doesn’t introduce issues.

NOTE

You’ll also hear developers refer to === (strict equality) as the “identity” operator.

WHO DOES WHAT

We had our descriptions for these operators all figured out, and then they got all mixed up. Can you help us figure out who does what? Be careful, we’re not sure if each contender matches zero, one or more descriptions. We’ve already figured one out, which is marked below:

image with no caption

Even more type conversions...

Conditional statements aren’t the only place you’re going to see type conversion. There are a few other operators that like to convert types when they get the chance. While these conversions are meant to be a convenience for you, the coder, and often they are, it’s good to understand exactly where and when they might happen. Let’s take a look.

Another look at concatenation, and addition

You’ve probably figured out that when you use the + operator with numbers you get addition, and when you use it with strings you get concatenation. But what happens when we mix the types of +’s operands? Let’s find out.

If you try to add a number and a string, JavaScript converts the number to a string and concatenates the two. Kind of the opposite of what it does with equality:

image with no caption

If you put the string first and then use the + operator with a number, the same thing happens: the number is converted to a string and the two are joined by concatenation.

What about the other arithmetic operators?

When it comes the other arithmetic operators—like multiplication, division and subtraction—JavaScript prefers to treat those as arithmetic operations, not string operations.

image with no caption

THERE ARE NO DUMB QUESTIONS

Q:

Q: Is + always interpreted as string concatenation when one of the operands is a string?

A:

A: Yes. However, because + has what is called left-to-right associativity, if you have a situation like this:

var order = 1 + 2 + " pizzas";

you’ll get “3 pizzas”, not “12 pizzas” because, moving left to right, 1 is added to 2 first (and both are numbers), which results in 3. Next we add 3 and a string, so 3 is converted to a string and concatenated with “pizza”. To make sure you get the results you want, you can always use parentheses to force an operator to be evaluated first:

var order = (1 + 2) + " pizzas";

ensures you’ll get 3 pizzas, and

var order = 1 + (2 + " pizzas");

ensures you’ll get 12 pizzas.

Q:

Q: Is that it? Or are there more conversions?

A:

A: There are some other places where conversion happens. For instance, the unary operator - (to make a negative number) will turn -true into -1. And concatenating a boolean with a string will create a string (like true + “love” is “true love”). These cases are fairly rare, and we’ve personally never needed these in practice, but now you know they exist.

Q:

Q: So if I want JavaScript to convert a string into a number to add it to another number, how would I do that?

A:

A: There’s a function that does this named Number (yes, it has a uppercase N). Use it like this:

var num = 3 + Number("4");

This statement results in num being assigned the value 7. The Number function takes an argument, and if possible, creates a number from it. If the argument can’t be converted to a number, Number returns.... wait for it..... NaN.

SHARPEN YOUR PENCIL

Time to test that conversion knowledge. For each expression below, write the result in the blank next to it. We’ve done one for you. Check your answers at the end of the chapter before you go on.

Infinity - "1"

_____________________

"42" + 42

“4242”

2 + "1 1"

_____________________

99 + 101

___________________

"1" - "1"

__________________

console.log("Result: " + 10/2)

____________________

3 + " bananas " + 2 + " apples"

___________________

image with no caption

We’re glad you’re thinking about it. When it comes to object equality there’s a simple answer and there’s a long, deep answer. The simple answer tackles the question: is this object equal to that object? That is, if I have two variables referencing objects, do they point to precisely the same object? We’ll walk through that on the next page. The complex question involves object types, and the question of how two objects might or might not be the same type. We’ve seen that we can create objects that look like the same type, say two cars, but how do we know they really are? It’s an important question, and one we’re going to tackle head on in a later chapter.

How to determine if two objects are equal

Your first question might be: are we talking about == or ===? Here’s the good news: if you’re comparing two objects, it doesn’t matter! That is, if both operands are objects, then you can use either == or === because they work in exactly the same way. Here’s what happens when you test two objects for equality:

When we test equality of two object variables, we compare the references to those objects

Remember, variables hold references to objects, and so whenever we compare two objects, we’re comparing object references.

image with no caption

Two references are equal only if they reference the same object

The only way a test for equality between two variables containing object references returns true is when the two references point to the same object.

image with no caption

SHARPEN YOUR PENCIL

Here’s a little code that helps find cars in Earl’s Autos parking lot. Trace through this code and write the values of loc1 through loc4 below.

image with no caption

The truthy is out there...

image with no caption

That’s right, we said truthy not truth. We’ll say falsey too. What on earth are we talking about? Well, some languages are rather precise about true and false. JavaScript, not so much. In fact, JavaScript is kind of loose about true and false. How is it loose? Well, there are values in JavaScript that aren’t true or false, but that are nevertheless treated as true or false in a conditional. We call these values truthy and falsey precisely because they aren’t technically true or false, but they behave like they are (again, inside a conditional).

Now here’s the secret to understanding truthy and falsey: concentrate on knowing what is falsey, and then everything else you can consider truthy. Let’s look at some examples of using these falsey values in a conditional:

NOTE

Some people write it “falsy.”

image with no caption

What JavaScript considers falsey

Again, the secret to learning what is truthy and what is falsey is to learn what’s falsey, and then consider everything else truthy.

There are five falsey values in JavaScript:

undefined is falsey.

null is falsey.

0 is falsey.

The empty string is falsey.

NaN is falsey.

To remember which values are truthy and which are falsey, just memorize the five falsey values—undefined, null, 0, “” and NaN—and remember that everything else is truthy.

So, every conditional test on the previous page evaluated to false. Did we mention every other value is truthy (except for false, of course)? Here are some examples of truthy values:

image with no caption

SHARPEN YOUR PENCIL

Time for a quick lie detector test. Figure out how many lies the perp tells, and whether the perp is guilty as charged, by determining which values are truthy and which values are falsey. Check your answer at the end of the chapter before you go on. And of course feel free to try these out in the browser yourself.

image with no caption

BRAIN POWER

What do you think this code does? Do you see anything odd about this code, especially given what we know about primitive types?

var text = "YOU SHOULD NEVER SHOUT WHEN TYPING";

var presentableText = text.toLowerCase();

if (presentableText.length > 0) {

alert(presentableText);

}

The Secret Life of Strings

image with no caption

Types always belong to one of two camps: they’re either a primitive type or an object. Primitives live out fairly simple lives, while objects keep state and have behavior (or said another way, have properties and methods). Right?

Well, actually, while all that is true, it’s not the whole story. As it turns out, strings are a little more mysterious. Check out this code:

image with no caption

How a string can look like a primitive and an object

How does a string masquerade as both a primitive and an object? Because JavaScript supports both. That is, with JavaScript you can create a string that is a primitive, and you can also create one that is an object (which supports lots of useful string manipulation methods). Now, we’ve never talked about how to create a string that is an object, and in most cases you don’t need to explicitly do it yourself, because the JavaScript interpreter will create string objects for you, as needed.

Now, where and why might it do that? Let’s look at the life of a string:

image with no caption

image with no caption

You don’t need to. In general you can just think of your strings as objects that have lots of great methods to help you manipulate the text in your strings. JavaScript will take care of all the details. So, look at it this way: you now have a better understanding of what is under the covers of JavaScript, but in your day to day coding most developers just rely on JavaScript to do the right thing (and it does).

THERE ARE NO DUMB QUESTIONS

Q:

Q: Just making sure, do I ever have to keep track of where my string is a primitive and where it’s an object?

A:

A: Most of the time, no. The JavaScript interpreter will handle all the conversion for you. You just write your code, assuming a string supports the object properties and methods, and things will work as expected.

Q:

Q: Why does JavaScript support a string as both a primitive and an object?

A:

A: Think about it this way: you get the efficiency of the simple string primitive type as long as you are doing basic string operations like comparison, concatenation, writing string to the DOM, and so on. But if you need to do more sophisticated string processing, then you have the string object quickly at your disposal.

Q:

Q: Given an arbitary string, how do I know if it is an object or primitive?

A:

A: A string is always a primitive unless you create it in a special way using an object constructor. We’ll talk about object constructors later. And you can always use the typeof operator on your variable to see if it is of type string or object.

Q:

Q: Can other primitives act like objects?

A:

A: Yes, numbers and booleans can also act like objects at times. However, neither of these has nearly as many useful properties as strings do, so you won’t find you’ll use this feature nearly as often as you do with strings. And remember, this all happens for you behind the scenes, so you don’t really have to think about it much. Just use a property if you need to and let JavaScript handle the temporary conversion for you.

Q:

Q: How can I know all the methods and properties that are available for String objects?

A:

A: That’s where a good reference comes in handy. There are lots of online references that are helpful, and if you want a book, JavaScript: The Definitive Guide has a reference guide with information about every string property and method in JavaScript. Google works pretty well too.

A five-minute tour of string methods (and properties)

Given that we’re in the middle of talking about strings and you’ve just discovered that strings also support methods, let’s take a little break from talking about weirdo types and look at a few of the more common string methods you might want to use. A few string methods get used over and over, and it is highly worth your time to get to know them. So on with the tour.

NOTE

A little pep talk: we could pull you aside and write an entire chapter on every method and property that strings support. Not only would that make this book 40 lbs and 2000 pages long, but at this point, you really don’t need it—you already get the basics of methods and objects, and all you need is a good reference if you really want to dive into the details of string processing.

THE LENGTH PROPERTY

The length property holds the number of characters in the string. It’s quite handy for iterating through the characters of the string.

image with no caption

the charAt method

The charAt method takes an integer number between zero and the length of the string (minus one), and returns a string containing the single character at that position of the string. Think of the string a bit like an array, with each character at an index of the string, with the indices starting at 0 (just like an array). If you give it an index that is greater than or equal to the length of the string, it returns the empty string.

NOTE

Note that JavaScript doesn’t have a character type. So characters are returned as new strings containing one character.

image with no caption

THE INDEXOF METHOD

This method takes a string as an argument and returns the index of the first character of the first occurrence of that argument in the string.

image with no caption

THE SUBSTRING METHOD

Give the substring method two indices, and it will extract and return the string contained within them.

image with no caption

You can omit the second index and substring will extract a string that starts at the first index and then continues until the end of the original string.

val = data.substring(5);

console.log("Substring is now " + val);

JAVASCRIPT CONSOLE

Substring is now phone|address

THE SPLIT METHOD

The split method takes a character that acts as a delimiter, and breaks the string into parts based on the delimiter.

image with no caption

STRING SOUP

image with no caption

Chair Wars (or How Really Knowing Types Can Change Your Life)

Once upon a time in a software shop, two programmers were given the same spec and told to “build it.” The Really Annoying Project Manager forced the two coders to compete, by promising that whoever delivers first gets one of those cool Aeron™ chairs all the Silicon Valley guys have. Brad, the hardcore hacker scripter, and Larry, the college grad, both knew this would be a piece of cake.

NOTE

Take a phone number of the form:

“123-4567”

and write code to accept or reject it. To be accepted the number should have seven digits, 0 through 9, with a dash in the middle.

The spec

Larry, sitting in his cube, thought to himself, “What are the things this code has to do? It needs to make sure the string is long enough, it needs to make sure the middle character is a dash, and it needs to make sure every other character is a number. I can use the string’s length property and I know how to access its characters using the charAt method.”

Brad, meanwhile, kicked back at the cafe and thought to himself, “What are the things this code has to do?” He first thought, “A string is an object, and there are lots of methods I can use to help validate the phone number. I’ll brush up on those and get this implemented quickly. After all, an object is an object.” Read on to see how Brad and Larry built their programs, and for the answer to your burning question: who got the Aeron?

image with no caption

In Larry’s cube

Larry set about writing code based on the string methods. He wrote the code in no time:

image with no caption

In Brad’s cube

Brad wrote code to check for two numbers and a dash:

image with no caption

But wait! There’s been a spec change

“Okay, technically you were first, Larry, because Brad was looking up how to use all those methods,” said the Manager, “but we have to add just one tiny thing to the spec. It’ll be no problem for crack programmers like you two.”

“If I had a dime for every time I’ve heard that one”, thought Larry, knowing that spec-change-no-problem was a fantasy. “And yet Brad looks strangely serene. What’s up with that?” Still, Larry held tight to his core belief that Brad’s fancy way, while cute, was just showing off. And that he’d win again in this next round and produce the code first.

BRAIN POWER

Wait, can you think of any bugs Brad might have introduced with his use of isNaN?

NOTE

Take a phone number of the form:

“123-4567”

and write code to accept or reject it. To be accepted the number should have seven digits, 0 through 9, with an optional dash in the middle.

What got added to the spec

Back in Larry’s cube

Larry thought he could use most of his existing code; he just had to work these edge cases of the missing dash in the number. Either the number would be only seven digits, or it would be eight digits with a dash in the third position. Quickly Larry coded the additions (which took a little testing to get right):

image with no caption

At Brad’s laptop at the beach

Brad smiled, sipped his margarita and quickly made his changes. He simply got the second part of the number using the length of the phone number minus four as the starting point for the substring, instead of hardcoding the starting point at a position that assumes a dash. That almost did it, but he did need to rewrite the test for the dash because it applies only when the phone number has a length of eight.

image with no caption

BRAIN POWER

Err, we think Brad still has a bug. Can you find it?

BRAIN POWER

How would you rewrite Brad’s code to use the split method instead?

Larry snuck in just ahead of Brad.

But the smirk on Larry’s face melted when the Really Annoying Project Manager said, “Brad, your code is very readable and maintainable. Good job.”

But Larry shouldn’t be too worried, because, as we know, there is more than just code beauty at work. This code still needs to get through QA, and we’re not quite sure Brad’s code works in all cases. What about you? Who do you think deserves the chair?

The suspense is killing me. Who got the chair?

image with no caption

Amy from the second floor.

(Unbeknownst to all, the Project Manager had given the spec to three programmers.)

image with no caption

IN THE LABORATORY, AGAIN

image with no caption

The lab crew continues to probe JavaScript using the typeof operator and they’re uncovering some more interesting things deep within the language. In the process, they’ve discovered a new operator, instanceof. With this one, they’re truly on the cutting edge. Put your lab coat and safety goggles back on and see if you can help decipher this JavaScript and the results. Warning: this is definitely going to be the weirdest code you’ve seen so far.

image with no caption

BULLET POINTS

§ There are two groups of types in JavaScript: primitives and objects. Any value that isn’t a primitive type is an object.

§ The primitives are: numbers, strings, booleans, null and undefined. Everything else is an object.

§ undefined means that a variable (or property or array item) hasn’t yet been initialized to a value.

§ null means “no object”.

§ “NaN” stands for “Not a Number”, although a better way to think of NaN is as a number that can’t be represented in JavaScript. The type of NaN is number.

§ NaN never equals any other value, including itself, so to test for NaN use the function isNaN.

§ Test two values for equality using == or ===.

§ If two operands have different types, the equality operator (==) will try to convert one of the operands into another type before testing for equality.

§ If two operands have different types, the strict equality operator (===) returns false.

§ You can use === if you want to be sure no type conversion happens, however, sometimes the type conversion of == can come in handy.

§ Type conversion is also used with other operators, like the arithmetic operators and string concatenation.

§ JavaScript has five falsey values: undefined, null, 0, “” (the empty string) and false. All other values are truthy.

§ Strings sometimes behave like objects. If you use a property or method on a primitive string, JavaScript will convert the string to an object temporarily, use the property, and then convert it back to a primitive string. This happens behind the scenes so you don’t have to think about it.

§ The string has many methods that are useful for string manipulation.

§ Two objects are equal only if the variables containing the object references point to the same object.

JAVASCRIPT CROSS

You’re really expanding your JavaScript skills. Do a crossword to help it all sink in. All the answers are from this chaper.

image with no caption

Across

Down

2. The only value in JavaScript that doesn’t equal anything.

5. The type of Infinity is ________.

7. There are _______ falsey values in JavaScript.

8. Who got the Aeron?

10. Two variables containing object references are equal only if they ______ the same object.

12. The value returned when you’re expecting an object, and that object doesn’t exist.

13. The ______ method is a string method that returns an array.

16. It’s always 67 degrees in _______, Missouri.

17. The type of null in the JavaScript specification.

18. The ______ equality operator returns true only if the operands have the same type and the same value.

1. The _________ operator can be used to get the type of a value.

2. The weirdest value in the world.

3. Your Fiat is parked at _____ Autos.

4. Sometimes strings masquerade as _________.

6. The value of a property that doesn’t exist.

9. There are lots of handy string ________ you can use.

11. The _______ operator tests two values to see if they’re equal, after trying to convert the operands to the same type.

14. null == undefined

15. To find a specific character at an index in a string, use the ______ method.

WHO AM I?

image with no caption

A bunch of JavaScript values and party crashers, in full costume, are playing a party game, “Who am I?” They give you a clue, and you try to guess who they are, based on what they say. Assume they always tell the truth about themselves. Fill in the blank next to each sentence with the name of one attendee. We’ve already guessed one of them.

Here’s our solution:

image with no caption

IN THE LABORATORY SOLUTION

image with no caption

In the laboratory we like to take things apart, look under the hood, poke and prod, hook up our diagnostic tools and check out what is really going on. Today, we’re investigating JavaScript’s type system and we’ve found a little diagnostic tool called typeof to examine variables. Put your lab coat and safety goggles on, and come on in and join us.

The typeof operator is built into JavaScript. You can use it to probe the type of its operand (the thing you use it to operate on). Here’s an example:

image with no caption

Now it’s your turn. Collect the data for the following experiments:

image with no caption

BACK IN THE LABORATORY SOLUTION

Oops, we forgot null in our test data. Here’s the missing test case:

var test10 = null;

console.log(typeof test10);

image with no caption

EXERCISE SOLUTION

We’ve been looking at some rather, um, interesting, values so far in this chapter. Now, let’s take a look at some interesting behavior. Try adding the code below to the <script> element in a basic web page and see what you get in the console when you load up the page. You won’t get why yet, but see if you can take a guess about what might be going on.

if (99 == "99") {

console.log("A number equals a string!");

} else {

console.log("No way a number equals a string");

}

image with no caption

SHARPEN YOUR PENCIL SOLUTION

For each comparison below write true or false below the operators == or === to represent the result of the comparison:

image with no caption

WHO DOES WHAT? SOLUTION

We had our descriptions for these operators all figured out, and then they got all mixed up. Can you help us figure out who does what? Be careful, we’re not sure if each contender matches zero, one or more descriptions. Here’s our solution:

image with no caption

SHARPEN YOUR PENCIL SOLUTION

For each expression below, write the result in the blank next to it. We’ve done one for you. Here’s our solution.

image with no caption

SHARPEN YOUR PENCIL SOLUTION

Time for a quick lie detector test. Figure out how many lies the perp tells, and whether the perp is guilty as charged, by determining which values are truthy and which values are falsey. Here’s our solution. Did you try these out in the browser yourself?

image with no caption

SHARPEN YOUR PENCIL SOLUTION

Here’s a little code that helps find cars in Earl’s Used Autos parking lot. Trace through this code and write the values of loc1 through loc4 below.

image with no caption

IN THE LABORATORY, AGAIN SOLUTION

image with no caption

The lab crew continues to probe JavaScript using the typeof operator and they’re uncovering some more interesting things deep within the language. In the process, they’ve discovered a new operator, instanceof. With this one, they’re truly on the cutting edge. Put your lab coat and safety goggles back on and see if you can help decipher this JavaScript and the results. Warning: this is definitely going to be the weirdest code you’ve seen so far.

image with no caption

JAVASCRIPT CROSS SOLUTION

You’re really expanding your JavaScript skills. Do a crossword to help it all sink in. All the answers are from this chaper. Here’s our solution.

image with no caption