PHP and JavaScript are both renowned to be languages with a lot of quirks. However two major initiatives on both sides, Hack for PHP and ES6 for JavaScript made the languages much better and modern. In this article I'm going to show all the ES6 features that are also in Hack.

Arrow Function

Both languages adopted the same shorter way to write functions. On JavaScript side, the main advantage is the automatic binding of this and for PHP it removes the need to declare all the variables you want to use from outside. ES6, Hack.

// JavaScript
var odds = evens.map(v => v + 1);
var nums = evens.map((v, i) => v + i);
nums.filter(v => {
  if (v % 5 === 0) {
    console.log(v);
    return true;
  }
  return false;
});
// Hack
$odds = array_map($v ==> $v + 1, $evens);
$nums = array_map(($v, $i) ==> $v + $i, $evens);
array_filter($nums, $v ==> {
  if ($v % 5 === 0) {
    echo $v;
    return true;
  }
  return false;
});

Class

JavaScript finally gets a class abstraction with ES6. It is however the bare minimal one to be useful, you cannot define constants, protected/private methods, traits ... PHP on this side is much better, without any Hack addition. ES6, PHP5.

// JavaScript
class SkinnedMesh extends THREE.Mesh {
  constructor(geometry, materials) {
    super(geometry, materials);
    this.idMatrix = SkinnedMesh.defaultMatrix();
    this.bones = [];
  }
  update(camera) {
    super.update();
  }
  static defaultMatrix() {
    return new THREE.Matrix4();
  }
}
// Hack
class SkinnedMesh extends THREE\Mesh {
  public function constructor($geometry, $materials) {
    parent::__construct($geometry, $materials);
    $this->idMatrix = SkinnedMesh::defaultMatrix();
    $this->bones = array();
  }
  public function update($camera) {
    parent::update();
  }
  static private function defaultMatrix() {
    return new THREE\Matrix4();
  }
}

Enhanced Object Literal

One long standing issue with object literals in JavaScript is the inability to use an expression as a key. This is fixed with the bracket notation in ES6. PHP 5.4 introduced a short notation for arrays as well. ES6, PHP.

// JavaScript
var obj = { [Math.random()]: true };
// Hack
$obj = [rand() => true];

Template Strings

Multiline strings and variable interpolations are something that have always been possible in PHP, yet they only start to work in ES6! ES6, PHP.

// JavaScript
var multiline = `In JavaScript this is
 not legal.`
var name = 'Bob',
    time = 'today';
`Hello ${name}, how are you ${time}?`
// Hack
$multiline = 'In PHP this is
 legal.';
$name = 'Bob';
$time = 'today';
"Hello $name, how are you $time?";

Default Arguments

It was possible to write default arguments in JavaScript but ES6 adds proper support for it right in the function declaration. Guess what, PHP had support for it all along. ES6, PHP.

// JavaScript
function f(x, y=12) {
  return x + y;
}
f(3) === 15;
f(2, 10) === 12;
// Hack
function f($x, $y=12) {
  return $x + $y;
}
f(3) === 15;
f(2, 10) === 12;

Iterator + for of

JavaScript has two ways to iterate on collections, either

for (var i = 0; i < array.length; ++i) { var element = array[i]; /* ... */ }
for (var key in object) { var element = object[key]; /* ... */ }

ES6 is now introducing a unified way to do iteration, that PHP always had, as well as a way to write custom collections via the iterator pattern, introduced in PHP5. ES6, PHP, PHP5.

// JavaScript
var fibonacci = {
  [Symbol.iterator]: function() {
    var previous = 0;
    var current = 1;
    return {
      next: function() {
        var new_previous = current; 
        current += previous; 
        previous = new_previous; 
 
 
        return {
          value: current,
 
 
          done: false
        }
      }
    }
  }
}
 
 
 
 
 
for (var n of fibonacci) {
  if (n > 1000) break;
  console.log(n);
}
// Hack
class Fibonacci implements Iterator<int> { 
  private $key = 0;    
  private $previous = 1;
  private $current = 0;
 
  public function next() { 
      $new_previous = $this->current; 
      $this->current += $this->previous; 
      $this->previous = $new_previous; 
      $this->key++; 
  } 
  public function current() { 
      return $this->current; 
  } 
  public function valid() { 
      return true; 
  } 
  public function key() { 
      return $this->key; 
  } 
  public function rewind() { 
      $this->previous = 1; 
      $this->current = 0; 
      $this->key = 0; 
  } 
}
foreach (new Fibonacci() as $n) { 
  if ($n > 1000) break; 
  echo $n; 
}

Generators

Python pioneered generators as another tool to manage control flow. It has originally been designed and promoted as an easier way to write iterators, but really shined as a better way to write asynchronous operations than callbacks. ES6, PHP5.

// JavaScript
var fibonacci = {
  [Symbol.iterator]: function*() {
    var previous = 1;
    var current = 0;
    for (;;) {
      var new_previous = current; 
      current += previous; 
      previous = new_previous; 
      yield current;
    }
  }
}
for (var n of fibonacci) {
  if (n > 1000) break;
  console.log(n);
}
// Hack
 
function fibonacci() {
  $previous = 1;
  $current = 0;
  for (;;) {
    $new_previous = $current; 
    $current += $previous; 
    $previous = $new_previous; 
    yield $current;
  }
}
 
foreach (fibonacci() as $n) { 
  if ($n > 1000) break; 
  echo $n; 
}

ES7 Async Await

C# introduced the concept of async/await combination to deal with asynchronous programming. The underlying implementation is very similar to generators but has proper syntax support. It is an addition of Hack on-top of PHP. ES7, Hack.

// JavaScript
async function chainAnimationsAsync(element, animations) {
  var result = null;
  try {
    for (var animation in animations) {
      result = await animation(element);
    }
  } catch (e) { /* ignore and keep going */ }
  return result;
}
// Hack
async function chainAnimationsAsync($element, $animations) {
  $result = null;
  try {
    foreach ($animations as $animation) {
      $result = await animation($element);
    }
  } catch (Exception $e) { /* ignore and keep going */ }
  return $result;
}

Map + Set

Both JavaScript and PHP are notorious for attempting to fit all the collection use cases into a single general purpose type. Both ES6 and Hack bring to the table proper support for Map and Set. ES6, Hack

// JavaScript
var s = new Set();
s.add('hello').add('goodbye').add('hello');
s.size === 2;
s.has('hello') === true;
 
var m = new Map();
m.set('hello', 42);
m.get('hello') === 42;
// Hack
$s = new Set();
$s->add('hello')->add('goodbye')->add('hello');
$s->count() === 2;
$s->contains('hello') === true;
 
$m = new Map();
$m->set('hello', 42);
$m->get('hello') === 42;

TypeScript

Last but not least, both languages are getting gradual typing. TypeScript, Hack.

// JavaScript
class Greeter<T> {
  greeting: T;
  constructor(message: T) {
    this.greeting = message;
  }
  greet() {
    return this.greeting;
  }
}
 
var greeter = new Greeter<string>("Hello, world");
console.log(greeter->greet());
// Hack
class Greeter<T> {
 
  public function __construct(private T $greeting) {}
 
 
  public function greet() {
    return $this->greeting;
  }
}
 
$greeter = new Greeter("Hello, world");
echo $greeter->greet();

Conclusion

With ES6 and Hack efforts, JavaScript and PHP are becoming languages with modern features. If you tried them 5 years ago, you should take another look, they are not as crappy as they once were :)

If you liked this article, you might be interested in my Twitter feed as well.
 
  • http://procoder.io Zach Silveira

    Really nice post, why aren't you using Ghost though?

  • Michael

    Your code examples are not that good. They are hard to read, should be commented better with meaningful variable names and in the same veins you should split functionality in methods with meaningful names. Clean Code ftw.

  • liberate_your_mind

    Are you serious?

  • Adir Amsalem

    The comparison between ES6 and Hack is incorrect. While ES6 is a direct continuation of ES5 and JavaScript, Hack isn't the same for PHP.

    I'm not knowledgeable enough in Hack, but as much as I understand - I think it'd be more appropriate to compare it to TypeScript or Dart.

  • http://blog.vjeux.com/ Vjeux

    ES6, TypeScript and Hack are superset of their host language. All the code that is written in PHP will also work in Hack. Same for ES6 and TypeScript.

    Dart is a completely different language, with different semantics and a different VM. You can run it in JS but they ship their entire VM. The same way you can run C++ in JS with emscriptem.

  • rsanchez1

    The major difference between ES6 and Hack, is that ES6 is being handled by a standards committee, while Hack is completely controlled by Facebook, one company.

  • bobopila

    You are wrong. ES6 is not a superset of Javascript. You have it backwards. ES6 is the language, Javascript is an implementation of the language, TypScript and CoffeeScript are the supersets of Javascript.

    Hack is to PHP what CoffeeScript is to Javascript.

  • bobopila

    It is not correct to talk about ES6 as being a superset of Javascript, it's almost the other way around.

    EcmaScript is the language, Javascript is the implementation of the language and is often called "dialect" http://stackoverflow.com/a/913064/933287

    CoffeeScript and TypeScript are superset of Javascript which in turn is interpreted by the EcmaScript version. For example, Chrome uses ES5, that means that you can use Javascript up to the point the Ecma version 5 allows you to use; so when Chrome upgrades its Ecma's version to ES6 then you'll be allowed to use the specifications of this new version.

  • http://blog.vjeux.com/ Vjeux

    Thanks for being precise. When I'm talking about JavaScript here I mean ES5. When I say A being a superset of B, I mean that every code that works in B will also work in A.

 

Related Posts

  • September 24, 2011 Javascript: Cyclic Object Detection (5)
    URLON.stringify() suffer from a problem, when passed an object that contains a cycle, it will never stop. This article shows 3 techniques in order to detect if an object is cyclical. Edit the object: Mark In order to detect a cycle in an object, the method we learn at school is to mark each v...
  • August 14, 2009 Mysqli Wrapper – Short and Secure Queries (28)
    Mysqli Wrapper is shortening the code required to run queries, make them 100% safe against SQL Injections and gives a handy Array as result. No more pain writing queries! You can view the source at the MysqliWrapper Github Repository. When developing a PHP application, SQL queries is th...
  • October 5, 2011 Javascript Presentation (1)
    The talk is over. Check out the Slides & Video. For several months now I've been surveying my friends and teachers at EPITA and I came to the conclusion that they have absolutly no idea what Javascript really is. In order to help them discover a language that is getting a lot of traction n...
  • November 4, 2013 Bitwise Truthiness (0)
    In this blog post, I explore another form of truthiness in Javascript. What happens if you use a bitwise operator on a value like 0|value or ~~value. Context We recently turned on the JSHint bitwise rule by default and the following code was caught. var isValid = false; for (var i = 0...
  • February 23, 2012 Dassault Systemes Javascript Evangelism Talk (0)
    I recently had the chance to do a 2-hour Javascript evangelism talk at Dassault Systèmes. Unfortunately the presentation has not been recorded. I reused my the presentation I did at EPITA at the beginning and added a second part with a lot of demos. I've written down notes about the second part s...