Saturday, August 21, 2010

Learning JavaScript

So I've decided to learn JavaScript. There are a couple of motivations behind this. The practical one is that I have various ideas that I think would be cool on hand-held devices like my Droid or an iPhone or iPad. The obvious drawback is writing for one platform is not going to be compatible with the other, and it is going to be hard enough to find time to write an app once, much less twice. However, if I write the app in JavaScript and make it available as a webpage, it is suddenly available everywhere.

The second motivation is some reading I've done on the web about how JavaScript is a misunderstood language, and it is more like Lisp than like Java. After reading this I felt I owed it to myself to at least learn something about the language, and stop being one of those people who looks down on it "because nobody wants to be a web developer. No self-respecting, rootin'-tootin', core-dump-debugging programmer wants to be one, anyway."

Oh, and let's not forget all of the amazing things Google has done with JavaScript.

JavaScript for Programmers

So to learn, I am going to be writing some programs and I will lean heavily on examples found on the web. Unfortunately, the majority of what is out there is geared towards non programmers. Meaning there is a lot of, "This is a variable. This is a loop. And, if you are ready for it, here is a function!" Or, as one book I saw in the library said, "JavaScript is a programming language, but don't let that scare you." What I am looking for is something geared towards programmers.

While I can't do it justice (only partially because I don't know anywhere near enough), here are a few things I've learned along the way. (and since some of my sources are old, this may be inaccurate).

What I've Learned So Far

Syntactically it is a C family language. So control structures (if, for, while, curly braces) work the way you'd expect.

JavaScript seems to have five types, though in some sense everything is an object.
  • boolean
  • number
  • string
  • object
  • function
Variables are passed by value to functions but, like Java, object variables are really references to the object, so for most purposes you can treat it as pass by reference. And yes, functions can be stored in variables and passed around. (Boy, I hope Java 7 really is going to include closures).

JavaScript is Object Oriented in the sense that everything is an object, but it doesn't have classes in the sense of Java and C++. However, you can treat it like it does, but I think then you are missing some of the power of JavaScript. It follows more of a property pattern, or what Steve Yegge calls the Universal Design Pattern.

So how do you use your own objects? (I'm going to ignore all the built in objects since you can go search the web for them yourself.)

Choice one - ad hoc
  1 var obj = new Object();
2 obj.name = 'hello world';
3 alert(obj.name);
Yep - you can just create an object and start assigning its properties, without defining them first. You can also treat these properties as if they were values in an associative array.
  4 var name = obj["name"];
Choice two - create a standard definition
  5 function Person(name, age) {
6 this.name = name;
7 this.age = age;
8 this.field = 'some value';
9
10 this.getOlder = function() {this.age++;}
11 this.changeName = personChangeName;
12 }
13 function personChangeName(newName) {
14 this.name = newName;
15 }
Note that inside this Person function (aka a constructor) we have access to a 'this' field which acts like this in Java. There are two methods defined in Person, done two different ways. The method getOlder is defined inline - which actually means that a new function is created every time this constructor gets called. If we refer to an existing method, like personChangeName, the function is only created once, but it still has access to the 'this' variable. Now, as expected, you can create a Person object and call its methods and access its fields.
 16 var bart = new Person("Bart Simpson", 10);
17 var me = new Person("Madking", 17); // I can pretend, right?
18 me.getOlder(); // Now I can vote!
19 alert(me.name + " is " + me.age + " and has field: " + me.field);
However, like the ad-hoc method, we can still attach new properties or methods to a Person object at any time.
 20 me.sayHi = function() { alert("hi: " + this.name); };
21 me.species = "Wannabe Blogger";
We can also assign properties to the function/Class itself. (ala static methods/variables)
 22 Person.staticVar = "not a constant";
23 Person.staticFunction = function() { /* do something */ };
There is a special Class variable called 'prototype'. Every instance automatically gets the fields and functions defined by its prototype.
 24 Person.prototype.sayBye = function() { alert("bye: " + this.name); };
25 Person.prototype.species = "Homo Sapien";
So every Person object (like "me") now has a function called "sayBye", and a field "species". However, individual objects can override these "inherited" properties. So the me object is still of species "Wannabe Blogger". Note that this means that even though it looks like "bart" and "me" are both instances of Person, this isn't true in the Java sense of the world. me has a "sayHi"method which bart doesn't have. Also note that you can add new fields and methods to both the objects and their prototype (thereby affecting all objects of this type that already or will exist) at any time.

Last couple notes

Arrays and Associative Arrays are commonly used data structures. In JavaScript, every object is an Associative Array mapping strings to anything. However you can also use non-negative integers as your key ala an array. And if the object is an Array object, it will have array-like methods and properties (like length). Arrays can be sparse, so you can have an array and assign element 0 and 100 and nothing in between, if you want. In this case, the length will be 101, i.e. the lowest unassigned index. There is also convenient literal syntax for defining arrays and associative arrays (objects) which is fairly self explanatory.
  1 var myArray = [1, 2, "mixed type", new Person("Lisa", 7), 3];
2 var myObject = {
3 name : "Homer",
4 age : 36,
5 wife : new Person("Marge", 34),
6 talk : function() { alert("DOH!"); }
7 };
Oh, and strings can be contained inside of either single or double quotes. Though it is poor style to randomly switch between them as I did in my examples above.

One other cool thing about JavaScript is the low barrier to entry. Open your favorite editor (or least favorite, doesn't matter), and create an html file. Put any/all of the code above inside a script tag. Nope open the file up in your browser of choice. VoilĂ , you have written a JavaScript program.
<script>
alert("java script is working!"); // replace with your own code
</script>
Yes, there is supposed to be an attribute in the script tag, and it should be embedded inside a body element of an html element, but this lazy approach seems to work if you are just playing around.

2 comments:

Unknown said...

Glad you're back to blogging. Any specific things (games) you're planning to build with this?

Michael Haddox-Schatz said...

I do have something specific I am planning on working on. If I actually get somewhere with it, I may blog about it. What I am planning on doing is blogging about the pieces as I write it. Which hopefully means I'll be blogging more regularly, though my posts will be less philosophical than they have been.