Syntactically, JavaScript and PHP are very similar. They're both loosely typed languages, and you can choose whether to write in an object-oriented or functional way.
However, there are some interesting differences, which a PHP developer may not have encountered before.
One example is asynchronous events. In PHP, everything happens linearly—when you call a function, the result is returned before the next line runs. However, in JavaScript, you can call some functions and have them return their results to a "callback" function a few seconds later.
The most obvious example is Ajax: when you request information from the server, it is bad design to have everything freeze while you're waiting for the data to return. Instead, you write your script such that the data is sent, and you carry on with other stuff. When the data returns, you handle it with another function.
This poses some interesting problems, such as race conditions, and how to pass variables through to remind the script what it was supposed to be doing when the Ajax request was fired.
A race condition occurs when one resource is accessed by two separate operations at the same time and one of them changes the value. This is because computers always do things one after the other; the change to the value will happen either before or after the other operation. This uncertainty means that in asynchronous systems, such as networks, care must be taken to make sure that things happen in the right order.
Race conditions are not a language-specific problem. They can happen anytime—say, when you open a file, work on it, and close it, only to find that at the time you were working on it, someone else came in and changed the name of the file. There are many ways of solving these problems depending on the nature of the case. The most common solution is to use a "lock", where if an operation is to write into a value, it will first "lock" it (usually by setting a flag variable or creating a .lock
file) before it reads it, and then will "unlock" it (remove the file or unset the flag) after it has completed its work.
When an asynchronous function is called and its return value is sent to a callback function, that callback function must be reminded what the caller function was doing, so that it can carry on with it. This can be done using closures. With closures, the callback function is generated by the caller function, and has a copy of the caller's environment, including what variables were set, among other things. Later in the book, you will see some examples of this.