5 Surprises for PHP Developers Coming to JavaScript

Unique features concealed within familiar syntax

PHP programmers often see the familiar C-like syntax of JavaScript and think it’s all flowers and roses. And while trivialities like loops and conditions are pretty much equivalent in both languages, things get very weird very quickly. Let’s take a look at the top 5 marvels JavaScript has to offer to the unsuspecting PHP veteran.

1. Functions are objects

Consider a function:

  function sum(a, b) {
    return a + b;
  }

It looks familiar, the only apparent difference being the missing $ to denote variables. But it turns out there’s more than that. The function sum() is actually an object. That means it can have properties and methods.

Something like:

 sum.length; // 2

… may come as a surprise. In this case length property of the sum object gives you the number of arguments this function expects.

And you’re not limited by built-in properties; you can assign any properties you like to the sum object. For example you can have a cache property that stores the results of previous (potentially expensive) calculations.

And since you can refer to functions just as regular variables, that means your function can take other functions as arguments (callbacks) and can also return functions as return values.

2. Function scope

In JavaScript all functions nested inside other functions can see the parent’s variables.

For example in PHP:

  // PHP
  function calc($a, $b) {
    $c = $a + $b;

    function plus5() {
      // $c is local and undefined
      var_dump($c); // NULL
      return $c + 5;
    }
    
    return plus5();
  }
  
  calc(1, 2); // 5

While in JavaScript:

  // JavaScript
  function calc(a, b) {
    var c = a + b;

    function plus5() {
      // nested functions see parent's variables
      console.log(c); // 3
      return c + 5;
    }
    
    return plus5();
  }
  
  calc(1, 2); // 8

It may not be too common to nest functions inside other functions in PHP, but it is very common in JavaScript.

3. Hoisting

Any variable defined anywhere in a function is moved (lifted, hoisted) to the top of the function and therefore visible anywhere inside the function. Combined with surprise #2 (inner functions see outer scope), it can come as a big surprise.

Consider this:

  var hi = "ho";
  function hello() {
    // global `hi` is visible
    console.log(hi); // "ho"
  }
  hello();

And then add a local `hi` further down:

  var hi = "ho";
  function hello() {
    // global `hi` is shadowed by the local
    console.log(hi); // undefined
    var hi = "bonjour";
    console.log(hi); // "bonjour"
  }
  hello();

This is happening because every variable defined in JavaScript gets an automatic undefined value. The local hi is hoisted to the top with its special undefined value. So it’s the same as writing:

  var hi = "ho";
  function hello() {
    var hi = undefined;
    // global `hi` is shadowed by the local
    console.log(hi); // undefined
    var hi = "bonjour";
    console.log(hi); // "bonjour"
  }
  hello();

4. No classes

JavaScript doesn’t have classes. Wait, what? What about object-oriented programming?

The thing is JavaScript supports object-oriented paradigms just fine. In fact, it’s trivial to define an object in JavaScript:

  var apple = {
    rotten: true
  };

And that is all you need to define an object called apple with a property called rotten and accessible as:

  apple.rotten; // true

This looks suspiciously similar to a hash (associative) array in PHP, cast to an object:

  $apple = (object)array(
    'rotten' => true
  );
  echo $apple->rotten; // true

Creating objects in JavaScript and adding properties is that simple. Ditto for adding methods:

  var apple = {
    rotten: true,
    isEdible: function () {
      return !this.rotten;
    }
  };
  
  apple.isEdible(); // false

You can augment (add more properties and methods to) objects at any time:

  apple.green = "was";
  apple.isGreen = function () {
    return this.green;
  };

5. Constructors and prototypes

But still, no classes?

You have probably seen JavaScript code that looks like:

  var fido = new Dog();

While that syntax looks like Dog is a class, in fact it’s just a function. And functions that add properties to the object referred to as this inside their body and are called with the new operator, are commonly known as “constructor functions.” And they do indeed look a lot like classes, although they are just functions.

In PHP:

  // PHP
  class Dog {
    var $name;
    function __construct($name) {
      $this->name = $name;
    }
  }
  
  $fido = new Dog('Fido');
  echo $fido->name; // "Fido"
 

In JavaScript:

  // JavaScript
  function Dog(name) {
    this.name = name;
  }

  var fido = new Dog('Fido');
  fido.name; // "Fido"

And how about methods of the Dog class (constructor function)? You can add them as properties to this, in which case they will be functions recreated for each “instance,” or you can add them to the special property called prototype, which is a property that all functions automatically get.

  Dog.prototype.getName = function () {
    return this.name;
  };
  Dog.prototype.say = function () {
    return 'Woof!';
  };

Properties and methods added to the `prototype` property are transparent to the user of the object:

  fido.say(); // "Woof!"

And prototypes are a way (one of many ways) to implement inheritance in JavaScript.

  function Wolf() {
    this.awesome = true;
  }
  
  Wolf.prototype.ears = 2;
  
  function Dog() {
    this.hugs = true;
  }
  
  Dog.prototype = new Wolf();
  
  var fido = new Dog();
  
  fido.ears; // 2
  fido.awesome; // true
  fido.hugs; // true

The good thing about JavaScript is that it’s accessible to you to learn and experiment with practically anywhere. All browsers these days have consoles built in. Sort of like playing with $ php -a on the command line. For example in both Firefox and Chrome you can load any page, click anywhere and select “Inspect Element.” You’ll get a set of developer tools that features a console. Using the console you can fiddle with the current page or simply explore and play with the language.

tags: , , ,