Why people think "JavaScript sucks"

It's popular

It's easier to make memes about it

There are only two kinds of languages: the ones people complain about and the ones nobody uses.

Created in 10 days

in 1995, it is now a quite different language

You are forced to use it

You have no choice on browser

Unknown Runtime

Every browsers has his own implementation of JavaScript

Too much tools

Mix between front-end and back-end modules

Too much modules

A

C v1.0

B

C v2.0

node_modules

a

b

node_modules

c

node_modules

c

A

C ^1.0

B

C ^1.1

node_modules

a

b

c

A

C v1.0

B

C v2.0

The left-pad incident

It's not JavaScript fault, but the community

Too much libraries

Back to the language

Async & Callbacks

fs.readdir(source, function (err, files) {
  if (err) {
    console.log('Error finding files: ' + err)
  } else {
    files.forEach(function (filename, fileIndex) {
      console.log(filename)
      gm(source + filename).size(function (err, values) {
        if (err) {
          console.log('Error identifying file size: ' + err)
        } else {
          console.log(filename + ' : ' + values)
          aspect = (values.width / values.height)
          widths.forEach(function (width, widthIndex) {
            height = Math.round(width / aspect)
            console.log('resizing ' + filename + 'to ' + height + 'x' + height)
            this.resize(width, height).write(dest + 'w' + width + '_' + filename, function(err) {
              if (err) console.log('Error writing file: ' + err)
            })
          }.bind(this))
        }
      })
    })
  }
})

Async & Callback

Solved with promises

const files = await readdir(source)

for (const file of files) {
	const file = await readFile(file)
    // ...
}
const files = await readdir(source)
const filesContent = await Promise.all(
  files.map(file => readFile(file))
)

Unpredictable Language

[] + [] // ''
[] + {} // Object
{} + [] // 0
{} + {} // NaN

Unpredictable Language

[3, 10, 1].sort() // [1, 10, 3]
['1', '2', '3']
  .map(parseInt) // [1, NaN, NaN]

Not typed

But there is TypeScript

Types are checked while transpiling

Dependency injection

<?php
class MaClass {

  private Dep1 $dep;

  function __construct(Dep1 $dep) {
  	  $this->dep = $dep;
  }

}

NestJS

import { Injectable } from '@nestjs/common';
import { Cat } from './interfaces/cat.interface';

@Injectable()
export class CatsService {
  private readonly cats: Cat[] = [];

  findAll(): Cat[] {
    return this.cats;
  }
}
import { Controller, Get } from '@nestjs/common';
import { CatsService } from './cats.service';
import { Cat } from './interfaces/cat.interface';

@Controller('cats')
export class CatsController {
  constructor(private catsService: CatsService) {}

  @Get()
  async findAll(): Promise<Cat[]> {
    return this.catsService.findAll();
  }
}

Adonis

import Route from '@ioc:Adonis/Core/Route'

Route.post('add-to-cart', async ({ request, response }) => {
  /**
   * Read cookie by name
   */
  const existingItems = request.cookie('cart-items', [])

  /**
   * Set/update cookie
   */
  const newItems = existingItems.concat([{ id: 10 }])
  response.cookie('cart-items', newItems)
})

Route.delete('clear-cart', async ({ response }) => {
  /**
   * Clear cookie
   */
  response.clearCookie('cart-items')
})

Single thread

Single thread

slice := []string{"a", "b", "c", "d", "e"}
sliceLength := len(slice)
var wg sync.WaitGroup
wg.Add(sliceLength)
for i := 0; i < sliceLength; i++ {
    go func(i int) {
        defer wg.Done()
        slowFunction(slice[i])
    }(i)
}
wg.Wait()
const slice = ["a", "b", "c", "d", "e"]
for (const item of items) {
    slowFunction(item)
}
function readFile(id) {
  const {file} = await mysql.first('SELECT file FROM files WHERE id = ?', [id])
  const content = await readFile(file)
  await mysql.execute('INSERT INTO post SET content = ?', [content])
}

await readFile(3)

Being critical

is important

Understanding is better

JavaScript sucks

By Jonathan Boyer

JavaScript sucks

  • 227