Why Javascript? That is a very good question: after seeing the multitude of programming languages we could have used, why js?
short answer: you don't have to install anything
Js is a fairly high-level language, which means that we won't have to try to teach you how to manage memory, make looping constructs, and hunt for prey all at the same time. We'll just teach you how to program as best as js will let us. However, js isn't all that great at some language features (*cough OOPcough*): so why should we even bother with it? First of all, looking to the right, we have a javascript interpreter built-in. No hassle with installing a compiler. Second, we'll just be teaching you how to think like a programmer (hopefully), and you'll be moving on soon. Third, it's nice to know when you need a quick little webpage effect, or hand-rolled form validation.
If you've ever even stepped into a computer science class once in your life, they must have figured out that you were uniniated and subjected you to writing a 'hello world' program. We won't do that here, because hello world programs are evil. Instead, we'll try getting you started off with a little something fun:
p>print("Master Foo is a cool person.")
var cool = ask("Are you cool?")
if(isTrue(cool))
{
print("No Way!!!")
} else {
print("pfft, loser")
exit()
}
print("well, since you're so cool, let's play a game")
var guess = 0
var randn = random(10)
var play = ask("I'm thinking of a number between 1 and 10.
If you guess right, I'll give you ten dollars.
Care to play?")
if(isTrue(play))
print("cool! Let's do it!")
else
print("too bad. You're playing any ways")
var count = 0
while(guess != randn)
{
var guess = ask("guess")
if(count == 3)
{
print("You failed three times! *eats you*")
guess = randn exit()
}
count++
}
print("Here's ten dollars. lucky")
click here to put that code in the code pane1, and run it. Maybe run it a few times, laugh at the utter uselessness of the program.
Now, you can notice just how much code we threw at you. If you don't think it's a little much, consider that most programmers start out with:
p>print("hello world")
and nothing more2( paste). But javascript is a pretty forgiving language, and you can still get out if you run RIGHT NOW!
Well, you're still here, so we'll dive into code. First, the program prints:
p>print("Master Foo is a cool person.")
Which is fairly straight forward3. The next statement4 is:
var cool = ask("Are you cool?")
is our first run-in with variables. The second part is easy to understand: expression asks the user for input on whether you are cool or not. If you're familiar with math, the first part should be easy; the variable cool is set equal to whatever you input in response to the question "Are you cool?", with the keyword var as the marker that tells the computer 'cool' is a variable. Let's say that you input "yes" as a response to the question; now if you did:
print(cool)
Then you would get "yes" back out. Now, the next block of code:
p>if(isTrue(cool))
{
print("No Way!!!")
} else {
print("pfft, loser")
exit()
}
It's what is known in a stuffy pretentious manner as a boolean expression, otherwise known as an if statement. If the expression in the parentheses is true, or (in the case of js) evaluates to not false, then the code in the first {} is executed. Otherwise, the code in the second brace set gets executed. So, if cool holds some value that is analougous to true, it'll print "No Way!", and print "pfft, loser" otherwise, and stop printing (exit).
The next five lines are are old-hat by now, except for that 'random' thing. It merely makes up a random number, from 0 to 105.
The next if... else..., though, is a little interesting: there's a programming rule that if there's just one statement after an if, then you don't need to wrap it in braces. If you have more than one statement, though, you'll need to wrap it up. Since most if statments start small, but start to ballon with more features, you'll probably want to just wrap all of your if... else... statements.
Now, we have a while loop. A loop executes a bunch of code over and over again while the condition, in the parentheses next to the while keyword, is true. Thus, while the guess variable doesn't hold a value equal to randn, do this stuff. That != thing? It just means 'not equal', just like the == a couple line below means 'equal'. Make sure you keep your == and = seperate in your mind! Putting one when you mean the other is a source of alot of programming errors.
In the if statment inside the loop, why do we bother to set guess to randn? While programming in a 'real' language, one could just do an exit() or equivalent and be done with the program, but in order to fit javascript into the browser, we don't really exit anything; instead, we just don't output the print or ask statements. Then, we need to break out of the loop before we're done, by setting guess = randn, therefore breaking out of the loop. It's a dirty hack, so if you're going to be spending more than 10 minutes playing with the in-browser javascript editor, try not to use exit().
Finally, what's this:
p>count++
mean? It's just a programmer's shorthand that means the same thing as:
p>count = count+1
Now, is your brain a-swirl? Yes? Okay, sit down, relax for a moment, because we'll be plunging into variables next.
If you haven't caught on to the concept of variables by now, perhaps an analogy will help: Let's say you are holding a beachball, which can have ping pong balls put into it. This beachball holds all our knowledge. The beachball is large, so we can only hold one beachball at a time. It the same time, we have another beachball which we name it x. As to how we name a ball, that is beyond us. It's a pet ball.
image - X and me
Now, let's say we wanted to evaluate (fancy speak for solve) 2 + 2, and we did so with the beachball we were holding:
image - me 2+2, animation
Hey, there are 4 ping pong balls in the beachball! But let's say we wanted to evaluate another expression like 5 + 13. If we threw out the 4 ping pong balls, we would lose the answer to 2+2, and we wouldn't know what 2+2 was anymore, because all of our knowledge is restricted to what is inside the beach balls. Since we have an extra beachball, though, we can do this:
transfer 2+2 to X, and then do 5+13
And everything is solved! We know that the answer to 2+2 is inside X, although we might not know that it is 4. But we want to know! But if we just pick up X, we'll have to put down a nameless ball, and how are we going to tell ourselves "pick up that ball"; well, which one6?! Let's make another beachball, Y:
Y
And put 5+13 into there. Then, we can observe both answers in turn, and our condendrum is solved. Let's say that a friend of ours wanted to know the sum of a list of numbers to another list of numbers, however, so that the first item of the first list is added to the first item of the second list, and the second item of the first list to the second item of the second list... like so:
x, y +
And he wants another list back. Now, you might think to make a list of variables, X1, X2, X3... to hold the sum of the lists, and give that to your friend. However, we don't know how big the list is going to be. Then, you say, I'll make the list bigger than I'll ever need it! Despite the fact you would have to write tons of code trying to get each set of variables to add correctly, and you would probably mistype something, you can make it much easier with loops and arrays. We'll be looking at loops later, but and array is a variable that is a list of values. So, instead of having X1, X2, X3... we can have one variable, X, that has items that can be accessed like this: X[0], X[1], X[2]... Wow, why do we start from 0? Well, truth be told, I'm not sure why anyone would count from zero, but it just happened that way, so the first item is accessed with [0], and the 50th item is accessed with [49].
We've been dealing with numbers for our entire talk of variables, but there's more types of variables, too. One is a string, or a string of characters, or a bunch of letters. If you thought it sounds like an array, you're right: it's an array of characters, and you can use the [c] operator on the end of a string to get the cth letter out. You can use strings like so:
p>var stringvariable = "hello" <!--a string variable-->
stringvariable[1] <!--e-->
stringvariable + " world" <!--hello world-->
The + sign is overloaded, meaning that it can be used both for math and strings; the math + is used with numbers, and the string + combines, or concatenates, them. Well, what if you did this:
p>"hello" + 13 <!--hello13-->
Because js is a weakly typed language, the result would be hello13. Because there is a string involved, js converts the number to a string and combines them as strings. Then, does this return 15:
p>"13"+2 <!--132-->
It's still a string, so it returns 132 instead. In order to get 15, you would have to explicitly convert "13" from a string to a number.
The other type we haven't even touched on is the boolean type. This type has only two settings, true or false. True is not the same as "true", although false is equal to "", and true is equal to 1 while false is equal to 0. If you want to see it yourself, paste this code to the pane and try running it:
p>alert("true == 'true' is" + true=="true")alert("false == '' is" + false=="")alert("true == 1" + true==1)alert("false == 0" + false==0)
Boolean types matter most in making decisions: if this is true, then do this. If my hair is bad today, don't go out. And that leads us very nicely into your discussion on how to control program flow.
Now, there are two different types of views in declaring types. One camp, the static types, says that types should be declared once and for all, and once declared so, the variable should always be that type: a number should always be a number, a string should always be a string. The other camp, the dynamic types, argue that such a restriction is unnecessary, and a variable is a variable, and programmers should be able to treat them as such. On one hand, static typing can make programs faster and use less memory. Dynamic typing, though, makes things easier for the programmer for a nearly non-existent price, as computers are now fast enough to handle dynamic typing. Js, if you haven't noticed, is a dynamicly typed language.
There is another issue that we just touched on: if you can add a string and a string, can you add a string and a number? If you can, that is a weakly typed language. If the computer cries that doing such an operation is an illegal adbomination, then you are programming in a strongly typed language. Strong typists maintain that weak typing is confusing and unnecessary: if you're going to concatenate a string and a number, do it the right way! Weak typists claim that their method is easier, and doesn't load the programmer with remembering boiler-plate code. Js, as we noted before, is a weakly typed language.
We've already met the ubiquitous if, but let's say that you wanted to know if a certain character was alphanumeric; that is, either a letter or a number. Using our friend the if, we would have something like:
p>if(character == 'a') return true;if(character == 'b') ...if(character == '9') return true;return false
which is alot of redundancy. Now, there's a construct called a switch statement which is better suited to this sort of problem:
p>switch(character){ case 'a': case 'b': .... case '9': return true; default: return false;}
You start out with a switch statment, much like the if, and then you have a set of parentheses and braces, just like the if. However, instead of an expression that comes out to a boolean true or false, you put the variable you wish to test against in there. Then, in the braces, there's a bunch of cases, and after each case, there's a character. The switch statement goes down the line, looking at each case to see if the value after it matches the test variable. If so, it starts executing after the :, and runs until it runs into a 'break' statment, or in this case, a return statement. That way, even though there's a case 'b': right after case 'a':, whenever the character is equal to 'a', it also evaluates what is evaluated by case 'b':. Here's an example
p>switch(beauty){ case "beautiful": case "gorgeous": case "intoxicating": print("you are beautiful!") break case "ugly": case "disgusting": print("ewwwwwww!!!") break}
So if beauty is equal to either "beautiful", "gorgeous", or "intoxicating", then it'll print "you are beautiful!" and break out of the switch statement, so it doesn't print "ewwwwww!!!" too.
Before we move onto loops, program flow is the way a program "flows" given a certain input. For instance, we have the program structured like this:
p>if(x){ ... if(b) { ... switch(c) { case d: ... break case e: ... break case f: ... break default: ... } ... } else { ... } ...} else { ...}
So, the program flow is defined by these if and switch statements; given this a, b, c, d, e, and f, which chunks of code will the program execute? If it helps, we can make an analogy with a river: the river flows from the top of the program, and everytime it hits an if or switch statement, it has to decide which way to go, uphill or downhill? And that's why they call the if and switch control statements.
Loops do the same bit of code over and over and over... okay, you get the picture. We've already introduced the while loop(which will execute as long as the condition inside the parentheses is true) but there are a couple other loops that might intrest you.
One is the for loop. Once you start getting into the nitty gritty of messing with arrays and looping through them, if you have a fixed-length array then you can loop through it using a variable declaration and a while statement, using ++ on the variable every time the while loop runs, like this:
p>var i = 0while(i < 10) <!-- the < means less than -->{ alert(i) i++}
will run the loop 10 times. Programmers use that sort of a loop so often that a for loop was developed to make it easy to write such loops:
p>for(var i =0;i<10;i++){ alert(i)}
Which does the same thing as the previous example. There are five parts to a for loop: the for keyword, the variable initializer, the test condition, the increment expression, and the code to be run for every iteration. The initializer, test condition, and increment expression are delimited with ;'s, which signify the end of a particular statement. In reality, you could add a ; to the end of each line of js, and it would still be correct, because either a ; or a new line signifies the same thing: a new statement.
The < is a new sort of comparison operator, like == and !=. In this case, if the variable i is less than 10, then it returns true. The same holds for >, except in reverse order, and if you add a = at the end of it, like <= or >=, then the expression will return true if the two values are also equal. Here's an example:
p>alert("1 > 3" + 1>3)alert("2 > 2" + 2>2)alert("1 < 3" + 1<3)alert("1 >= 3" + 1>=3)alert("1 <= 3" + 1<=3)alert("2 <= 2" + 2<=2)
Going back to loops, we have one final loop for your enjoyment: the do-while loop.
p>var x = ""do { x = prompt("hello")} while(x!="10");
This loop looks like a while loop, except it's on it's head, and has a little do at the beginning. Because the while is at the end, the loop body (inside the braces) is executed at least once. If we didn't use a do-while loop, the equivalent while loop would be:
p>var x = prompt("hello")while(x!="10"){ x = prompt("hello")}
Which doesn't look terribly bad. And you're right: in most cases, using a for or while loop should suffice. But if you need a loop to execute at least once, then do while could be very useful.
Let's say that we wanted going to loop for every element in an array. We could do:
p>for(var i=0;i
which is all well and good. However, it's not very readable. We could instead write:
p>for(i in array){ alert(i)}
Which is much more readable, and cleaner too. If you need the index number, though, you'll have to add your own itinerator to the for-in loop, or stick with the messier for.
Now we are at the very heart of programming: defining your own functions. If you program long enough, you'll eventually run into a set of code that you have to type over and over again. It's not that you didn't use a loop, but it's just this piece of code does something you need done in more than one place.
p>alert(variable + "pinapples!")
This piece of code adds "pineapples!" to the end of everything, and then alerts you to the fact. However, after writing reams of code, you decide that you hate pineapples. Instead, you would like to add "bannanas!" to the end of each string, not "pineapples!". So now you have to go through and replace every "pineapples!" with "bannanas!", and hope you don't miss any.
Functions, though, can make your life a whole lot easier.
p>function shout(str){ alert(str + " bannanas!")}
First off, the keyword function tells js that what will follow is a function definition that you can use elsewhere. Next, the function name is given, which is shout. This is the name with which you will access the function, so choose it wisely. The next thing, (str), is called an argument list. Why they call them arguments, who knows. But you pass them to the function like so:
p>shout("no")
which would then alert you to the fact that "no bannanas!" Who knows what that means, but now you can change bannanas to oranges, and as long as you used the function shout, you could change everything to apples just as easily. Also, the name is a dead give-away to what the code is supposed to do: emulate a shout. Without the function, you could only guess what the code meant out of context. This is called an abstraction, whereas code is gathered together as an idea, and put to work as an idea. Shouting is an abstraction: we can open our mouths, move our vocal chords, and breath, but we there isn't just one action we do to 'shout'. Putting together all these actions, though, can produce shouting.
While some functions are fine with just doing something with their arguments, other functions return a value; a function call to:
p>eat('bannana')
could return 'yellow poop'. That's what functions can do: return a 'processed' form of the arguments.
Before we move on, I just really want to hit on something that is a somewhat important topic: recursive calls to functions. If you can do recursion, then the sky's the limit. Let's say we have
function x(a){ if(a > 10) { return a+x(a-1) } return 0 }alert(x(15))
Now, the computer will alert you to the number 75. If you notice, there's a small call to x inside the definition of x! If we had done this:
function x(){ x()}
Then we would be in a real pickle, because it would never end. In this case, though, the function does stop evaluating, and we'll indicated what x(12) does:
x(12)=> return 12+x(11)return ( 12 + return ( 11 + x(10) ) )return ( 12 + return ( 11 + 0 ) ) <!-- Because x(10) will return 0 -->return ( 12 + 11 )return ( 23 )23
The same process happens for x(15), just a for a longer time. x(30000), though, won't return anything. There's a recursion error: too much recursion, as the computer can only handle so much recursion.
We'll be looking at another way of using functions next, and then going through a couple of examples, so if you feel a little shaky on functions, you'll get plenty of practice!
Whew, oop7. So we talked about how functions are an abstraction of code, but what about data? We would much rather think in terms of objects rather than pure numbers and strings. That is where oop comes into play: it defines data as an object, and puts functions to work on those objects. Abstractions working on abstractions to make the charade complete, eh? An example:
p>function person(){this.height = 5this.weight = 140this.IQ = 100this.eat = eatthis.grow = growthis.study = studythis.irradiate = irradiate}function eat() {this.weight += 10} function grow(){this.weight +=5this.height += 1.2}
function study() {this.IQ += 10}
function irradiate() {this.weight -= 20this.IQ -= 15}
var bob = new person() bob.eat()bob.grow()
Right at the bottom, we have three lines of code. First, we make a new variable named bob, then we assign a new person to him. Then, he eats, grows, and gains weight and height accordingly, just like regular people. If we wanted to weight him, we would just add
p>alert(bob.weight)
Get it? So up at the top, we define a person object. Js is weird because it does objects by defining only functions, whereas most languages have another keyword to define the a new sort of object. Well, each to his own, but this is how js does it.
So, the person function contains a bunch of declarations with 'this.' prefixed to them. That is js's way of adding elements to an object: in this case, adding the weight, height, and IQ elements to the person object. Then, what are the next couple of statements? Eat, grow, and irradiate aren't variables; they're functions! To operate on the person object, though, they must be added as methods to the object they operate on. Remember the definition of oop; abstracted operations on abstract data types. The operations that act on objects aren't the same as functions, despite the fact that javascript names them functions, because they functions never were meant to be attached to an object; they just accept arguments and return values.
So by using:
p>this.method = outsidefunction
You can later do this:
p>object.method()
In which the method acts on the object.
Got that? If it doesn't make sense now, you can try Java's oop model: it's much more logical and easier to intuitively grasp. Or, you can stick to it and wade through these examples: one uses oop.
If you do any appreciable amount of website building from scratch, you'll eventually use forms of some sort. Let's say that we're working for a site devoted to bannanas, specifically the feedback form. However, alot of people screw up in filling out the form, which is overly complex for no reason whatsoever. If someone screws up their form, they system automatically rejects their feedback. For some reason, the website has been getting less and less hits. The webmaster, seeing this, wants you to make a script to make sure people fill out the form correctly.
Here's the form:
p>
Hello
Now that we've banged our heads against a terribly contrived business-related example, let's play with squares! People call it dhtml, whereas you combine html, css, and javascript to make a dynamic webpage. It's not ajax8, persay, but it uses the same elements. So, let's meet the square:
p>square object
and paste to it. So let's make the square move:
p>dx and dy
And apply it to the square to make it do something cool:
p>spiral
Now, let's change the color while it does some other moves:
p>move and change color
And now, let's make it bigger!
p>bigger
HAHAHAH I'm sure you fell for it! No? darn!...
And finally...
p>More fun with a bigger family!
We sure hope you have fun playing around with the family! However, we need to move onto greener pastures, or perhaps a coffeepot, with java.