CCATP #446 – Programming by Stealth – 18 of x JavaScript Miscellany

In this episode of Programming By Stealth, Bart Busschots takes us through the final stages of learning JavaScript within the playground. Now that we know about objects, we need to re-visit the arguments object present in every JavaScript function. We need to take a detailed look at the typeof operator, and we need to look at some built-in objects and functions JavaScript provides. We also need to look at how JavaScript handles regular expressions, and finally, we need to introduce the concept of exception handling. Bart’s full written tutorial is available at bartbusschots.ie/….


itunes
mp3 download

During this episode we briefly mention a wonderful email from Jill about factorials and more. I wanted to include the full letter in the shownotes here because it contains some wonderful explanations, especially an even better explanation of strongly vs. weakly-typed languages. Here’s Jill’s entire letter:

Hi, me again

I think there’s a concept you haven’t quite grasped in PBS, and that’s types. I know you’ve mostly got it, but I think perhaps I might be able to help unconfuse you on a few edge cases.

Types and Values

Let’s start with the basics. Every variable has both a type and value. This is true in all computer languages, not just Javascript. In a strongly-typed language like Swift, the type constrains what the value can be. In a weakly-typed language like Javascript, the value dictates the type. But either way, every variable always has both – and that’s important.

One consequence is that there’s no such thing as “nothing”. Bart may have misled you there. In Javascript, as in all computer languages, there is always a type, and there is always a value. A string is a sequence of zero or more characters. For example, “cat” is the string having the three charcters ‘c’, ‘a’ and ‘t’. A string which has zero characters is called an “empty string” – but – remember what I said – everything has both a type and a value. An empty string has a value (the sequence consisting of zero characters), so in that sense you might think it’s sort-of-nothing, but remember, it still has a type, and the type of this particular value is string.

If a variable has type string, then its value is constrained to be a sequence of zero or more characters. But a sequence of zero characters is still a string. If its type is string, it’s a string.

Strongly-typed vs Weakly-typed

Let me show you one of the differences between a strongly-typed language and a weakly-typed language. In Javascript (weakly-typed), you can do this:

var s = "hello"
s = 42

In the first line, variable s becomes a string consisting of five characters, ‘h’, ‘e’, ‘l’, ‘l’ and ‘o’. Then, in the second line, variable s is overwritten with an integer (not a string) with value 42. In Javascript, that works. But now let’s try that in Swift (which is strongly-typed)…

var s = "hello"
s = 42 // <----- This line is an ERROR

In Swift, the second line is an error, and the file won't compile, because, well, once a string, always a string. Once we've declared s to be a string, it can never be an integer. It can never be anything but a string.

In a strongly-typed language, you always know the type of every variable. But in a weakly-typed language, you don't, but you can test it. In Javascript, the typeof operator returns the type of its argument (as a string).

Types in Functions

This is where the difference between strongly-typed and weakly-typed languages really shows. Let's write a function which returns two times the argument. This is what it looks like in Swift:

func twoTimes(n: Int)
{
return 2 * n
}

and this is what it looks like in Javascript:

function twoTimes(n)
{
return 2 * n
}

The keyword difference ("func" vs "function") is superficial, so ignore it. That's just vocabulary. It's not grammar; it's not important. What is important is that in Swift, we explicitly state that n is an integer. (That's what the ": Int" is doing). And in Javascript, we don't. And that means, inside the body of the function, in Swift, we know that n is an integer. Guaranteed. In Javascript, we have no such guarantee. In Javascript, n could be of any type.

That's why Bart is trying to teach you not to write functions like the above. Bart would prefer you to write something like this:

function twoTimes(n)
{
if (typeof(n) != "number") return NaN
return 2 * n
}

Bart wants you to do, by hand, what the language is not doing for you. He's trying to make a weakly-typed language behave like a strongly-typed language, by doing the type-checking explicity.

I have to tell you, most people don't do this. Most people who write Javascript just keep track of types in their head. You, as the code author, know that you're only ever going to feed numbers into this function. The correct answer to "What would happen if you passed a string into this function?" should be (in my opinion), "I will never pass a string into that function". That's why I chose Javascript.

This is just my opinion now - I know Bart will disagree! If type-checking matters to you, then you're using the wrong languange. If type-checking matters to you, then you should be using a strongly-typed language. But that's just my opinion, as I said. Best not to argue with the teacher. 🙂

Value-checking, on the other hand, is something that matters regardless of language. There is no such thing as a "strongly-valued" language, so checking the value is something you'll always have to do explicitly. If you ask the user to type in a number between 1 and 10, you will have to check that user didn't type 11, and that will be true in every language, even Swift.

Hopefully, that last paragraph made sense to you because you've understood the difference between type and value.

And so, back to Nothing

Javascript has exactly seven different types. They are called: undefined, boolean, number, string, function, symbol and object.

If the type is undefined, then the only possible value is undefined.

If the type is boolean, then there are only two possible values: true and false.

If the type is number, then the value is a real number (which could be an integer).

If the type is string, then the value is a sequence of zero or more characters.

If the type is function, the value is a function (something that you can later "call" or "invoke").

(The other two types are too advanced for now. Let's wait for Bart to cover them).

So you can see, there are many different kinds of "nothing" - each distinguished by type. The empty string is a kind of nothing, but it has type string. Undefined is a kind of nothing, but it has type undefined. There is even something called null - which is yet another kind of nothing, but that has type object.

Remember those equals-signs?

(a == b) is true if a and b have the same value
(a === b) is true if a and b have both the same value and the same type

So (3 == "3") is true, because they have the same value. (Javascript will auto-convert the number into a string in order to do the comparison). But (3 === "3") is false, because the two operands differ in type.

Oh, and just to annoy us, the negative tests are != and !== (not !== and !===). There's one fewer equals sign than you might expect.

Undefined and Optional Function Parameters

Suppose I have a function like this:

function doSomething(x)
{
// do something
}

You can see, it expects exactly one argument. Within the body of the function, we can refer to this argument using the variable name x.

Now suppose that, elsewhere in the program. we call the function like this:

doSomething() // Look, no argument!

In this case, the function will be called when the above line is executed. At that point, the flow of control enters the body of the function, and so now x exists. By now, I think you will probably understand exactly what x will contain: It will contain the particular flavor of nothingness that we call undefined. And that means you can test for it. You can rewrite the function to do, for example, this:

function doSomething(x)
{
if (typeof(x) == "undefined")
{
x =1;
}
// do something
}

and viola! You now have a function with an optional parameter.

Optional parameters are very useful. This is something you might want to do on purpose.

Incidently, in Swift, we would do the same thing like this:

func doSomething(x: Int = 1)
{
// do something
}

Again, in Javascript, we are having to do something by hand that in other languages is built in. In the Swift version the function can be called with either no parameters (in which case x will be 1 within the function) or with exactly one parameter (which must be an integer), in which case x will be that value within the function.

Output

Bart confused you by using the word "output" ambiguously. I think I can help there.

When a function computes a value and hands that value back to the code that called it, that's called returning. You use the return statement to do that.

When a function displays information to a human being, that's called printing. In Bart's playground, you use the function pbs.say() to do that.

Try to avoid the word "output". Bart uses it ambiguously for both of the above meanings.

One More Thing

As a math nerd, I'm surprised you didn't correct Bart on a couple of math mistakes. Specifically:
The product of zero numbers is 1, not 0
The factorial of zero is 1, not 0

The first can be easily demonstrated by raising any number to the power of zero - that's effectively multiplying zero numbers together. The second is obvious because for any n, n! equals ((n+1)! / (n+1)). Or you can just look it up on the internet.

All the best,
Jill

Leave a Reply

Your email address will not be published.

Scroll to top