DEV Community

Cover image for PHP 8 features I wish also existed in JavaScript
Andreas
Andreas

Posted on • Updated on

PHP 8 features I wish also existed in JavaScript

I know there is still a lot of hatred for PHP out there, but in my opinion with version 7 at the latest (which is already over 5 years old!), PHP evolved to a great language that is fun and even type-safe to use. Next to Just-In-Time compilation, which may give a big performance boost to PHP applications, version 8 brings a lot of useful features.

I want to present three of them I really wish I could use in JavaScript as well. I hope that comes in handy especially for those, who didn't take a look at PHP 8 yet. Let's go!

#1 Named arguments

Let's assume, you have a function foo with 6 parameters a to f having different default values and now you want to call that function passing the argument false for the last parameter only.

PHP 8:

foo(f: false);
//-----^
Enter fullscreen mode Exit fullscreen mode

JavaScript:

foo('test', 42, true, 'bar', 5.5, false);
//--------------------------------^
Enter fullscreen mode Exit fullscreen mode

In JavaScript passing arguments to a function is solely based on the parameter position, unfortunately. I know that named arguments can be simulated by using objects and destructuring, but a native feature would be much more convenient here.

See RFC: Named Arguments

#2 Match expression

The new match expression of PHP is very similar to the switch statement, except it is an expression and can be used to directly assign values to a variable or return values. This comes in very handy, if you have more than two possible values for assignment.

PHP 8:

$fontWeight = match ($weight) {
  100, 200      => "Super Thin",
  300           => "Thin",
  400, 500      => "Normal",
  600, 700, 800 => "Bold",
  900           => "Heavy",
  default       => "Not valid"
};
Enter fullscreen mode Exit fullscreen mode

JavaScript:

let fontWeight = '';
switch (weight) {
  case 100:
  case 200:
    fontWeight = "Super Thin";
    break;
  case 300:
    fontWeight = "Thin";
    break;
  case 400:
  case 500:
    fontWeight = "Normal";
    break;
  case 600:
  case 700:
  case 800:
    fontWeight = "Bold";
    break;
  case 900:
    fontWeight = "Heavy";
    break;
  default:
    fontWeight = "Not valid";
    break;
}
Enter fullscreen mode Exit fullscreen mode

The match expression may be simulated by a JavaScript object, but that would require an additional variable (thus more reserved memory) and will fail for cases, where the checked values aren't allowed to be used as object keys.

See Docs: match

#3 Optional Chaining

Chaining only if the needed property exists is a very elegant way to query objects. In PHP you can do this now with the nullsafe operator.

PHP 8:

$country = $session?->user?->getAddress()?->country;
Enter fullscreen mode Exit fullscreen mode

JavaScript:

const country =
  session && session.user && session.user.getAddress() && session.user.getAddress()['country']
  ? session.user.getAddress()['country']
  : null;
Enter fullscreen mode Exit fullscreen mode

In JavaScript you still have to check step by step, if the corresponding property exists. There is a corresponding TC39 proposal which is in stage 4 by now and I'm really looking forward to this being part of the ECMAScript Specs.

See RFC: Nullsafe Operator

Wrap it up

So we saw a small selection of the new PHP 8 features that would also be a great addition to JavaScript. Maybe you have other PHP features in mind that are missing in JavaScript or you know a better JavaScript counterpart to the above problems than me? Great! Let's discuss it in the comments.


Edited: 10th of February 2021 (extended match example)
Published: 8th of February 2021

Latest comments (63)

Collapse
 
techmonkey profile image
Cocoko

Bruh, the optional chaining was introduced to javascript back in 2020 javascript.plainenglish.io/new-ope...

you should do a little research before publishing this kind of stuff

Collapse
 
andho profile image
Amjad Mohamed

What about 200, 500, 700 and 800?

Collapse
 
duongductrong profile image
Trong Duong

In the section #3 Optional Chaining, i think it was exists in javascript

Collapse
 
thodwris profile image
Theodoros Kokosioulis

Can you elaborate more on how the #2 works?

Collapse
 
shuckster profile image
Conan • Edited

Didn't realise PHP had such nice language features these days!

Here's a JS solution for #2 just for fun:

// Helpers
//
const memoize = (fn, cache = new Map()) =>
  x => cache.has(x)
     ? cache.get(x)
     : cache.set(x, fn(x)).get(x)

const matchMaker = lookFor => 
                   haystack => 
                   needle => 
                     lookFor(needle, haystack)

const match = matchMaker((needle, haystack) => {
  const found = haystack
    .filter(x => Array.isArray(x[0]))
    .find(x => x[0].includes(needle))
  return found !== undefined 
    ? found[1] 
    : haystack.find(x => x.length === 1)[0]
})

// Implementation
//
const fontSize = memoize(match([
  [[100, 200],        "Super Thin"],
  [[300],             "Thin"],
  [[400, 500],        "Normal"],
  [[600, 700, 800],   "Bold"],
  [[900],             "Heavy"],
  [/* default */      "Not valid"],
]))

;[100, 200, 300, 400, 500, 600, 700, 800, 900, 901]
  .forEach(size => {
    console.log(`${size} = `, fontSize(size))
  })

// 100 =  Super Thin
// 200 =  Super Thin
// 300 =  Thin
// 400 =  Normal
// 500 =  Normal
// 600 =  Bold
// 700 =  Bold
// 800 =  Bold
// 900 =  Heavy
// 901 =  Not valid
Enter fullscreen mode Exit fullscreen mode

I included a memoizer just so that it would (with usage) have the "lookup-iness" of switch, but obviously it's not quite as elegant as PHP's match!

Collapse
 
devmount profile image
Andreas

Awesome, thank you for this addition πŸ˜πŸ‘πŸ»

Collapse
 
shuckster profile image
Conan • Edited

To follow this up, I've since learned about an upcoming TC39 spec on adding pattern-matching to JavaScript.

It's Stage 1 -- so a long way off -- but there are many libraries available that offer it, now including my own.

I even reused your font-size example in the README. :)

Collapse
 
shuckster profile image
Conan

No worries! Nice article. πŸ‘

Collapse
 
roganoalien profile image
Rodrigo GarcΓ­a

Optional chaining is now available in newest ES.

Collapse
 
juancarlospaco profile image
Juan Carlos

I use this since years ago with Nim lang.
I think Scala also has them.

Collapse
 
murkrage profile image
Mike Ekkel

Loads of folks saying that named arguments is possible using an object have a fair point. I’d still like to see it as an actual feature, tho! It could be an optional thing.

Collapse
 
devmount profile image
Andreas

Exactly what I was thinking πŸ‘πŸ»

Collapse
 
bramus profile image
Bramus!
Collapse
 
devmount profile image
Andreas
  • What if you want to check for values, that aren't allowed as object key? Also an object would require additional (unnecessary) memory and handling of multiple values with the same assignment isn't very elegant either.
  • Thank you for this information πŸ‘πŸ»
  • That's awesome, I've already read that in other comments.
Collapse
 
ogrotten profile image
ogrotten • Edited

darn near anything is allowable as an object key. Besides that, that's a high corner case.

const x = {
["\$&n"]: 12
}

x["\$&n"]
12

I tried to paste this here in a code block, but it wouldn't show.

Collapse
 
devdufutur profile image
Rudy NappΓ©e • Edited


$fontWeight = match ($weight) {
100 => "Super Thin",
300 => "Thin",
400 => "Normal",
600 => "Bold",
900 => "Heavy"
};

Error prone code... What's the value of $fontWeight if $weight = 101 ? Is there an error ?

Safe "Switch expressions" constructs should assert there is always a default clause (i'm looking at you rust 😍)

Collapse
 
devmount profile image
Andreas • Edited

match has a default case too. Also, you can comma-separate multiple values:

$fontWeight = match ($weight) {
  100, 200 => "Super Thin",
  300 => "Thin",
  400, 500 => "Normal",
  600, 700, 800 => "Bold",
  900 => "Heavy",
  default => "Not valid"
};
Enter fullscreen mode Exit fullscreen mode

Edited the example in the article accordingly.

Collapse
 
ouzsrcm profile image
ouzsrcm

Waaw, is this php? İ'm not sure. So beatiful 🀩

Collapse
 
devmount profile image
Andreas

πŸ˜πŸ‘πŸ»

Collapse
 
maacpiash profile image
Ahad Chowdhury

All these features happen to be available in C#. Named arguments are in C# since version 4, switch expressions since 8, and null-conditional operator since 6.

Collapse
 
oskarcodes profile image
Oskar Codes

For your last point, there is the optional chaining operator that just came to JavaScript in 2020: developer.mozilla.org/en-US/docs/W...

Collapse
 
jonrandy profile image
Jon Randy πŸŽ–οΈ • Edited

You can do all of this (or something damn close) already in JS in almost all modern browsers. You dont even need TypeScript (but that's true as a general statement anyway!)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.