debuggable

 
Contact Us
 

A PHP developers guide to JavaScript - Part I

Posted on 30/12/06 by Felix Geisendörfer

Hey folks,

after the overwhelming interest in me writing a little bit about javascript on this blog, here comes my first post on that topic. It's actually the beginning of a little series (2 or 3 parts) that is going to be targeted at php developers who've only used JS by merging snippets/libraries together without really learning the language itself. For all of those posts please keep in mind that I'm mainly on the php site of town as well, but my recent trips to downtown javascript have hopefully taught me well ; ).

The JS developer toolkit

Coming from PHP you are probably spoiled with some good developer tools, especially Zend Studio or Ecplipse PHP. In javascript land there are not as many good editors out there. From the ones I've worked with I would recommend Notepad++. It's very light weight, supports numerous languages, can completely replace your windows notepad and I use it for all my JS (and CSS) needs right now. If you don't run the beautiful microsoft operating system (...) you might find Aptana interesting. It's based on eclipse and therefor runs on most major operating systems. It also has advanced support for code completion and some other gimmicks. Personally I don't use it because it's too memory hungry, especially when my php IDE is already opened. Other then that it's a really comfortable IDE to work with.

Now that you have an editor (no matter which one) you might want to start coding right away. But you shouldn't. Not because you couldn't, but because you still lack the most important JS (and web dev) tool that is available these days: Firebug. Without any question, it is the most advanced debugging tool out there. So please take some time to get to know it's features and learn how to use it, it will make your day.

The Basics

As all of you are already familiar with coding in php, I won't start at "Hello World", but I'll try to show some important differences in JS (from PHP) and point you to some resources for further reading. The first one would be gotAPI.com. If you see me using a function you are not familiar with, that's always a good place too look it up. (Side note: It also has support for the CakePHP/jQuery API).

Variables:

Just like PHP, javascript is a weakly typed language. This means you won't have to declare variable types (even so you can) and all variable types are converted to strings automatically when needed. The symbol used for gluing different strings together is '+' and not '.' like in php.

var myVariableA = 'Thinking';
var myVariableB = 'PHP'

// Logs: ThinkingPHP
console.log(myVariableA+myVariableB);

Oh and in case you wonder: 'console' is no default javascript object. It's only available when using firebug (or Firebug Lite). The usual JS way to get information is to use the alert() function. But the first time you produce and endless loop with an alert in it, you'll get to appreciate the console.log function offered by Firebug ; ). Another thing you just learned is that object functions/properties are accessed via '.' (as opposed to '->' in php), but more about this later.

Arrays

The good news is, javascript has decent support for indexed arrays. The bad news is, it's lacking associative arrays (that we php folks all know and love). But don't you worry, there is a workaround to fix this.

Working arrays in JS is very much like working with arrays in php. The only difference is that arrays (like everything else) in JS are actual objects not only variables containing literals. But that's a no-brainer, just have a look at the following examples:

// Note: var myArray = []; works just as well).
var myArray = new Array();

// Assign three values to the array.
myArray[0] = 'ThinkingPHP';
myArray[1] = 'suddenly';
myArray[2] = 'thinks';

// Now to show you we are working with an object:
console.log(myArray.length); // Will log: 3

// myArray[] = 'value'; does not work in javascipt, so we have to use Array.push
myArray.push('JavaScript');

// Will log: ThinkingPHP suddenly thinks JavaScript.
console.log(myArray.join(' ')+'.');

Now without really getting to the objects part yet, the Arrays are a good example to show another default behavior of the javascript language:

// This is notation to declare an array with one or more values (comma separated)
var varA = ['Thinking'];
var varB = varA;

// Push PHP at the end of array varB
varB.push('PHP');

// Display the results: ["Thinking", "PHP"]
console.log(varA);

In case the result of this little test surprises you, here is what happened: When executing 'var varB = varA;' you are not simply copying the value of variable 'varA', you are actually creating a reference to it. So if we would want to port this snippet to PHP, it would look like this:

$varA = array('Thinking');
$varB = &$varA;

// Push PHP at the end of array varB
array_push($varB, 'PHP');

// Prints: Array ( [0] => Thinking [1] => PHP )
print_r($varA);

So in case you actually wanted to create a copy of varA, this is how to do it in JS:

var varA = ['Thinking'];

// Clone the array
var varB = new Array();
for (var i=0; i<varA.length; i++)
{
    varB[i] = varA[i];
}

varB.push('PHP');

// Logs: ["Thinking"]
console.log(varA);

// Logs ["Thinking", "PHP"]
console.log(varB);

Of course there are ways to do this in a more elegant way by creating a clone function, but let's keep it simple for now. Let's go back to what I said at the beginning of the array section: "Javscript does not support associative arrays". Yes, this is really a bummer at first. But the workaround is fairly simple, all it takes is to use objects instead:

Objects

One of the things that really have caused my to like javascript a lot recently is the great flexibility it offers. This really shows when working with objects the first time. In PHP you think of an object as an instance of a specific (fixed) class that basically consists of functions and properties. Well this is true for objects in JS as well. They have functions and properties. Where JS is different is the way you create an object. Unlike PHP where you define types of objects as classes, in javascript you often create objects on the fly. Another important point is that JS objects often do behave like associative arrays in php as well (but they are usually called hashes in JS).

Just consider the following example:

// same as var myJsObject= {};
var myJsObject = new Object();

// This looks like a typical associative array in PHP
myJsObject['varA'] = 'Thinking';
myJsObject['varB'] = 'PHP';

// But what's that? We are attaching a function to the object on the fly
myJsObject['ThinkingWhat'] = function()
{
    // 'this' refers to the class this function resides in here. However this is not always the case in JS, more about this later.
    console.log(this.varA, this.varB);
}

// Call the ThinkingWhat function
myJsObject['ThinkingWhat']();

// is the same as
myJsObject.ThinkingWhat();

Ok, I hope you are not too confused right now. You basically have to accept that in Javascript there is no difference between the object['propery'] and object.property notation. Another good example would be the little Array snippet we've already used:

var varA = ['Thinking'];
var varB = varA;

// Instead of varB.push('PHP') we can write:
varB['push']('PHP');

// Display the results: ["Thinking", "PHP"]
console.log(varA);

Now that you know this little JS secret, it's time to show you another one. The object we created on the fly a second ago, could have equally well been written like this:

var myJsObject =
{
    varA: 'Thinking',
    varB: 'PHP',
    ThinkingWhat: function()
    {
        console.log(this.varA, this.varB);
    }
};

The two syntaxes are equal to one another. One of the most popular usages of the second syntax right now is JSON. So if you didn't know what JSON was so far, it's simply sending javascript objects via AJAX and then eval'ing them on the client site so they can directly be accessed. However, please keep in mind that in JSON you always have to put quotes around object properties (!).

Functions

Alright, even if you've not done much JS coding so far, you've probably seen a simple JS function before:

// Logs: ThinkingPHP
console.log(ThinkingWhat('PHP'));

// A simple function with one argument
function ThinkingWhat(what)
{
    // Return 'Thinking' plus the contents of the what argument
    return 'Thinking'+what;
}

Now before I'll continue and reveal javascript's dark & nasty secret about functions (don't be scared, it's actually cool once you know how to deal with it), I want to show you a little bit more about passing arguments:

// Logs: ThinkingPHP
console.log(ThinkingWhat('PHP'));

// Logs: Thinkungundefined (and display no error)
// This means: Unlike in PHP, all function arguments in JS are optional on default (!)
console.log(ThinkingWhat());

// A simple function with one argument
function ThinkingWhat(what)
{
    // Return 'Thinking' plus the contents of the what argument
    return 'Thinking'+what;
}

// Logs: ThinkingPHP
console.log(FreeThinking('Thinking', 'PHP'));

function FreeThinking()
{
    // In all functions the arguments object is available. It's an array
    return arguments[0]+arguments[1];
}

Alright, this should be simple to understand. The two main lessons learned here are that in JS all function arguments are optional on default, and you always have access to an arguments object inside a function. You can think of it similiar to "$arguments = func_get_args()" in PHP. Now one thing you might miss is the ability to assign default values to parameters (like you do with optional parameters in PHP). Here is what to do:

// Logs: ThinkingPHP
console.log(ThinkingWhat());

// Logs: ThinkungJS
console.log(ThinkingWhat('JS'));

// A simple function with one argument
function ThinkingWhat(what)
{
    // If what doesn't contain a value (that would evaluate to true) then assign 'PHP' to it
    what = what || 'PHP';
   
    // Return 'Thinking' plus the contents of the what argument
    return 'Thinking'+what;
}

I really like the elegance this has. I know I often find myself writing if statements for checking empty variables and overwriting their contents with something else in PHP, so this is definitely a pretty cool feature of the JS language.

Ok, do you still remember me talking about the JS dirty little secret about functions? Well here it comes: The things what we just have looked at as 'functions' are actually a little bit more in JS. They are fully qualified class definitions (and btw. the only way to create them). This is probably the point were PHP developers feel odd and I agree that this takes a while to get used to. Nevertheless, check out this example to see how your innocent little function becomes a class:

// Defines a class named Blog
function Blog(url, author)
{
    this.url    = url;
    this.author = author;
   
    this.visit = function()
    {
        // Redirects the user to the url of this blog
        window.location.href = this.url;
    }
}

// Creates an instance of the Blog class called ThinkingPHP
var ThinkingPHP = new Blog('http://www.thinkingphp.org', 'Felix Geisendörfer');

// Logs: 'http://www.thinkingphp.org'
console.log(ThinkingPHP.url);

// Navigates to 'http://www.thinkingphp.org'
ThinkingPHP.visit();

Now as you can see the Blog function now doesn't just serve as a static function any longer. It has become the constructor and wrapper for the class Blog that contains two member variables (url and author) as well as one function (visit).

One of the most powerful JS features related to classes is the prototype property. It is a list of all members any given class has and can also be used to modify already created classes (and all instances of it). You've probably heard about the Prototype framework which makes extensive usage of this feature by adding new functions to already existing DOM element classes. Personally I don't use this feature very often and prefer to not modify existing objects (that's also one of the reasons I prefer jQuery over Prototype), but here is how to work with the prototype property regardless of that:

// Defines a class named Blog
function Blog(url, author)
{
    this.url    = url;
    this.author = author;
}

// Creates an instance of the Blog class called ThinkingPHP
var ThinkingPHP = new Blog('http://www.thinkingphp.org', 'Felix Geisendörfer');

// This adds the function getAuthorFirstName to *all* Blog classes (also already created instances like ThinkingPHP)
Blog.prototype.getAuthorFirstName = function()
{
    // Splits the author string at ' ' and returns the first value of that array
    return this.author.split(' ')[0];
}

// Logs: 'Felix'
console.log(ThinkingPHP.getAuthorFirstName());

As you can see, even so we added the getAuthorFirstName function after we created the ThinkingPHP instance of the Blog class, it's still available in the instance of it. If you wonder of the practical usage of this: I find this feature pretty useful to modify 3rd party JS classes without actually touching the source of them. Because just like you can add class members using their prototype property, you can also overwrite existing ones.

This was part I

Alright, this was the first part of my 'A PHP developers guide to JavaScript' series. I hope you guys enjoyed it and I was able to communicate the most important aspects of JS in an easy-to-understand manner. I'm sorry it took me so long to publish this, but writing this required several hours so I had to split it up over several days. If you find errors, have questions or want to suggest anything I'd appreciate a comment ; ).

For Part II, I plan to cover things like scope, events, some JS coding techniques and will probably also start talking about jQuery a little bit. Meanwhile I'd recommend everybody to read Sergio Pereira's Quick guide to somewhat advanced JavaScript which I think has a lot of good information in it and is a little bit more detailed then my post on here.

Oh and before I forget: A Happy New Year to all of you! (Sorry I didn't care enough about Christmas to send out a greeting ^^). And also Happy Birthday to Daniel's cakebaker blog that just turned 1 year old!

-- Felix Geisendörfer aka the_undefined

 
&nsbp;

You can skip to the end and add a comment.

Daniel Hofstetter said on Dec 30, 2006:

Thanks for this informative post (and the gratulations). Is that correct, that you have to remove the console.log statements if you put the scripts live?

Christian Tietze said on Dec 30, 2006:

Wow Felix, this post is a pretty cool introduction to JS! I understand the "language quirks" a lot better now and don't have to read lots of tutorials which show me how to show "Hello World" or the basics of programming.

I really like this article the way it is :)

Felix Geisendörfer said on Dec 30, 2006:

Daniel: Well if you target browsers other then FF with Firebug installed then yes, you should probably remove them ; ). But if you don't want to do this, you can either include Firebug lite (http://www.getfirebug.com/lite.html), a JS script that will provide the console for other browser, or you can also write your own log function like this:

if (!console || !console.log)
{

var console =

{

log: function()

{

alert(arguments.join(', '));

}

}

}

Chris Norton said on Dec 30, 2006:

Kudos on a great little introduction! I've been dabbling in Javascript a nit lately so this post was timely for me.

I must say, I've used Notepad++ as my primary text editor almost a year now and I love it. In fact, when I moved to Linux several months ago I tried out Wine (www.winehq.com) just to see if I could get it running! For those interested: yes, it runs fine under Linux + Wine. :)

As for Aptana I think it is a great editor and has plenty of features to make me want to use it (eg. FTP sync, code templates, CVS/Subversion integration) but unfortunately it is completely unstable (at least with Ubuntu 6.10 running Java 1.5) which makes it unusable. Hopefully this problem will clear up soon and I can give it a real test run.

I'm looking forward to reading the next articles in the series!

Tom said on Dec 30, 2006:

Thanks a lot Felix, in Austria there's a charity called "Licht ins Dunkel", thats the same you did with the JS thingy to my brain ;)

PS: Is there a digg story i'd love to push?

DingoNV  said on Dec 30, 2006:

thanks felix!
i suddenly feel the ice of javascript objects melting away quickly ;)

my understanding of JS objects has just jumped the fence to teh enlightened side.

I can't wait for parts 2 and 3, and teh firebug recommendation was definitely a huge help too!

Mladen Mihajlovic said on Dec 31, 2006:

Hey Felix that's great, thanks. I really like how you explain these things in a very simple and easy to understand way.

MP:Schorsch said on Dec 31, 2006:

great .. it took me a while to find this stuff out after i started with jQuery half a year ago. So this will definitly be of great use for JS Beginners

Felix Geisendörfer said on Dec 31, 2006:

MP:Schorsch: Yeah, I didn't know much JS before jQuery either. When playing around with prototype before, I picked up some knowledge but not too much. The amazing elegance of jQuery was what finally made me really interested in JS and I learned a lot by just reading the jQuery source code (even so it tends to be a little cryptic for compression reasons sometimes).

anonymous  said on Jan 02, 2007:

s/getAuhtorFirstName/getAuthorFirstName/

Felix Geisendörfer said on Jan 02, 2007:

Hey anonymous, I initially wasn't sure if your comment was SPAM but a closer look at it made me recognize that you compressed your communication efforts and pointed out a typo in my post ; ). Thanks for that.

Nima said on Jan 04, 2007:

I eagerly waiting for other parts, your article save my time alot.
Thanks.

konqueror user  said on Jan 05, 2007:

whats good:

It's a nice approach to compare php and js syntax. Both languages are somehow depening on each other more and more every day.
Everything is explained in a simple way, definately the way one must talk to php programmers.

whats bad:

Is that an article on javascript or an advertisement for some firefox XUL debugger tool ?

In this article, the code snippets are useless unless the reader has the same configuration as the writer. That's a big mistake a lot of web-designers do .. believing the whole world is like their own screen ... billions of coulours and huge monitor.

Please provide a substitute to this console stuff in your examples, this article just confused me into downloading and compiling some crappy crippled commercial version of FF, just because of a buggy-console-that mixes-css/js/xml-warnings-all-together appears to be mandatory in the examples ..

next try it'd be nice not to confuse your readers introducing XUL apps calls in your JS/PHP example ... or call it "A PHP developers guide to JavaScript/XUL - Part I"

Felix Geisendörfer said on Jan 05, 2007:

Hey konqueror user,

thanks for your feedback. I wrote this article on a 17" screen with 1024x768 so I might not fit the typical web developer with real world blindness clichee. It's true that all code posted here depends on the console.log() funtion, but right after the first code snippet I explained what it was, how to use it *without* Firebug (Firebug Lite, a JS snippet to simply include) and I also mentioned that alert() is the usual way for output things in JS.

Now I agree that it might not be a good idea to confront somebody new to programming and JS by depending on an XUL tool for FF, but that's not my target audience. My audience are people who have a good understanding for php programming, web development and most of them (71%) use Firefox as their main browser. And Firebug itself is a truly exceptional and amazing web development tool, I cannot see how anybody would not prefer it over polluting his code with alert() statements. But I'll try to be more clear about the things I said above in my next post, because I certainly didn't mean to make anybodies life harder with the console.log() stuff, I just thought that's one of the things I wished to have had from day 1.

[...] sorry for my low activity on here again. The 2nd part of my A PHP developers guide to JavaScript series is in the works but I might need some more days to finish it since I'm still very busy. I've just done 2 little side projects next to my big client project and I'm also working hard on releasing my first own web application (it's still secret - somewhat) so there was little time for blogging. [...]

Eran Galperin said on Apr 26, 2007:

In JavaScript, Objects can (and should) be used as associative arrays. There's a blog on the subject by Andrew Dupont - here http://www.andrewdupont.net/2006/05/18/javascript-associative-arrays-considered-harmful/

Spot said on Aug 10, 2008:

Felix,

This is exactly what I have been looking for. Something to learn JS by anchoring it to my PHP experience. Just wonderful.

Where are the other two?! Please!! :)

saran  said on Jan 16, 2009:

how can access php variables into java file?

This post is too old. We do not allow comments here anymore in order to fight spam. If you have real feedback or questions for the post, please contact us.